xref: /illumos-gate/usr/src/cmd/bnu/cu.c (revision 3b296559ccf4430268fec1fbbb543f59c9a7113b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
22462be471Sceastha /*
23462be471Sceastha  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24462be471Sceastha  * Use is subject to license terms.
25462be471Sceastha  */
26462be471Sceastha 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * cu [-cdevice] [-sspeed] [-lline] [-bbits] [-h] [-t] [-d] [-n]
327c478bd9Sstevel@tonic-gate  *		[-o|-e] [-L] [-C] telno | systemname [local-cmd]
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  *	legal baud rates: 300, 1200, 2400, 4800, 9600, 19200, 38400.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  *	-c is used to specify which device will be used for making the
377c478bd9Sstevel@tonic-gate  *		call.  The device argument is compared to the Type (first)
387c478bd9Sstevel@tonic-gate  *		field in the Devices file, and only those records that
397c478bd9Sstevel@tonic-gate  *		match will be used to make the call.  Either -d or -t
407c478bd9Sstevel@tonic-gate  *		would be more intuitive options designations, but they
417c478bd9Sstevel@tonic-gate  *		are already in use.
427c478bd9Sstevel@tonic-gate  *	-l is for specifying a line unit from the file whose
437c478bd9Sstevel@tonic-gate  *		name is defined in /etc/uucp/Devices.
447c478bd9Sstevel@tonic-gate  *	-b is for forcing the number of bits per character processed on
457c478bd9Sstevel@tonic-gate  *		the connection. Valid values are '7' or '8'.
467c478bd9Sstevel@tonic-gate  *	-h is for half-duplex (local echoing).
477c478bd9Sstevel@tonic-gate  *	-t is for adding CR to LF on output to remote (for terminals).
487c478bd9Sstevel@tonic-gate  *	-d can be used  to get some tracing & diagnostics.
497c478bd9Sstevel@tonic-gate  *	-o or -e is for odd or even parity on transmission to remote.
507c478bd9Sstevel@tonic-gate  *	-n will request the phone number from the user.
517c478bd9Sstevel@tonic-gate  *	-L will cause cu to go through the login chat sequence in the
527c478bd9Sstevel@tonic-gate  *		Systems file.
537c478bd9Sstevel@tonic-gate  *	-C will cause cu to run the local command specified at the end
547c478bd9Sstevel@tonic-gate  *		of the command line, instead of entering interactive mode.
557c478bd9Sstevel@tonic-gate  *	Telno is a telephone number with `=' for secondary dial-tone.
567c478bd9Sstevel@tonic-gate  *	If "-l dev" is used, speed is taken from /etc/uucp/Devices.
577c478bd9Sstevel@tonic-gate  *	Only systemnames that are included in /etc/uucp/Systems may
587c478bd9Sstevel@tonic-gate  *	be used.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  *	Escape with `~' at beginning of line:
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  *	~.	quit,
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  *	~![cmd]			execute shell (or 'cmd') locally,
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  *	~$cmd			execute 'cmd' locally, stdout to remote,
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  *	~%break	(alias ~%b)	transmit BREAK to remote,
697c478bd9Sstevel@tonic-gate  *	~%cd [dir]		change directory to $HOME (or 'dir'),
707c478bd9Sstevel@tonic-gate  *	~%debug (alias ~%d)	toggles on/off the program debug trace,
717c478bd9Sstevel@tonic-gate  *	~%divert		allow unsolicited diversions to files,
727c478bd9Sstevel@tonic-gate  *	~%ifc (alias ~%nostop)	toggles on/off the DC3/DC1 input control,
737c478bd9Sstevel@tonic-gate  *	~%ofc (alias ~%noostop)	toggles on/off the DC3/DC1 output control,
747c478bd9Sstevel@tonic-gate  *		(certain remote systems cannot cope with DC3 or DC1).
757c478bd9Sstevel@tonic-gate  *	~%old			recognize old style silent diversions,
767c478bd9Sstevel@tonic-gate  *	~%put from [to]		put file from local to remote,
777c478bd9Sstevel@tonic-gate  *	~%take from [to]	take file from remote to local,
787c478bd9Sstevel@tonic-gate  *
797c478bd9Sstevel@tonic-gate  *	~l			dump communication line ioctl settings,
807c478bd9Sstevel@tonic-gate  *	~t			dump terminal ioctl settings.
817c478bd9Sstevel@tonic-gate  *
827c478bd9Sstevel@tonic-gate  *	Silent diversions are enabled only for use with the ~%take
837c478bd9Sstevel@tonic-gate  *	command by default for security reasons. Unsolicited diversions
847c478bd9Sstevel@tonic-gate  *	may be enabled using the ~%divert toggle. The 'new-style'
857c478bd9Sstevel@tonic-gate  *	diversion syntax is "~[local]>:filename", and is terminaled
867c478bd9Sstevel@tonic-gate  *	by "~[local]>", where 'local' is the nodename of the local
877c478bd9Sstevel@tonic-gate  *	system. This enables ~%take to operate properly when cu
887c478bd9Sstevel@tonic-gate  *	is used over multiple hops. 'old-style' diversion syntax may
897c478bd9Sstevel@tonic-gate  *	be enabled using the ~%old toggle. ('old-style' diversion
907c478bd9Sstevel@tonic-gate  *	should be avoided!)
917c478bd9Sstevel@tonic-gate  *
927c478bd9Sstevel@tonic-gate  *	Cu no longer uses dial.c to reach the remote.  Instead, cu places
937c478bd9Sstevel@tonic-gate  *	a telephone call to a remote system through the uucp conn() routine
947c478bd9Sstevel@tonic-gate  *	when the user picks the systemname option or through altconn()--
957c478bd9Sstevel@tonic-gate  *	which bypasses /etc/uucp/Systems -- if a telno or direct
967c478bd9Sstevel@tonic-gate  *	line is chosen. The line termio attributes are set in fixline(),
977c478bd9Sstevel@tonic-gate  *	before the remote connection is made.  As a device-lockout semaphore
987c478bd9Sstevel@tonic-gate  *	mechanism, uucp creates an entry in /var/spool/locks whose name is
997c478bd9Sstevel@tonic-gate  *	LK.<MAJ>.<maj>.<min> where MAJ is the major device of the
1007c478bd9Sstevel@tonic-gate  *	filesystem containing the device, and <maj> and <min> are the
1017c478bd9Sstevel@tonic-gate  *	major and minor of the device.
1027c478bd9Sstevel@tonic-gate  *	When cu terminates, for whatever reason, cleanup() must be
1037c478bd9Sstevel@tonic-gate  *	called to "release" the device, and clean up entries from
1047c478bd9Sstevel@tonic-gate  *	the locks directory.  Cu runs with uucp ownership, and thus provides
1057c478bd9Sstevel@tonic-gate  *	extra insurance that lock files will not be left around.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate #include "uucp.h"
1097c478bd9Sstevel@tonic-gate #include <locale.h>
1107c478bd9Sstevel@tonic-gate #include <stropts.h>
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate #define	MID	BUFSIZ/2	/* mnemonic */
1137c478bd9Sstevel@tonic-gate #define	RUB	'\177'		/* mnemonic */
1147c478bd9Sstevel@tonic-gate #define	XON	'\21'		/* mnemonic */
1157c478bd9Sstevel@tonic-gate #define	XOFF	'\23'		/* mnemonic */
1167c478bd9Sstevel@tonic-gate #define	TTYIN	0		/* mnemonic */
1177c478bd9Sstevel@tonic-gate #define	TTYOUT	1		/* mnemonic */
1187c478bd9Sstevel@tonic-gate #define	TTYERR	2		/* mnemonic */
1197c478bd9Sstevel@tonic-gate #define	HUNGUP  2
1207c478bd9Sstevel@tonic-gate #define	YES	1		/* mnemonic */
1217c478bd9Sstevel@tonic-gate #define	NO	0		/* mnemonic */
1227c478bd9Sstevel@tonic-gate #define	IOERR	4		/* exit code */
1237c478bd9Sstevel@tonic-gate #define	MAXPATH	100
1247c478bd9Sstevel@tonic-gate #define	NPL	50
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate int Sflag=0;
1277c478bd9Sstevel@tonic-gate int Cn;				/*fd for remote comm line */
1287c478bd9Sstevel@tonic-gate jmp_buf Sjbuf;			/*needed by uucp routines*/
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate /*	io buffering	*/
1317c478bd9Sstevel@tonic-gate /*	Wiobuf contains, in effect, 3 write buffers (to remote, to tty	*/
1327c478bd9Sstevel@tonic-gate /*	stdout, and to tty stderr) and Riobuf contains 2 read buffers	*/
1337c478bd9Sstevel@tonic-gate /*	(from remote, from tty).  [WR]IOFD decides which one to use.	*/
1347c478bd9Sstevel@tonic-gate /*	[RW]iop holds current position in each.				*/
1357c478bd9Sstevel@tonic-gate #define	WIOFD(fd)	(fd == TTYOUT ? 0 : (fd == Cn ? 1 : 2))
1367c478bd9Sstevel@tonic-gate #define	RIOFD(fd)	(fd == TTYIN ? 0 : 1)
1377c478bd9Sstevel@tonic-gate #define	WMASK(fd)	(fd == Cn ? line_mask : term_mask)
1387c478bd9Sstevel@tonic-gate #define	RMASK(fd)	(fd == Cn ? line_mask : term_mask)
1397c478bd9Sstevel@tonic-gate #define	WRIOBSZ 256
1407c478bd9Sstevel@tonic-gate static char Riobuf[2*WRIOBSZ];
1417c478bd9Sstevel@tonic-gate static char Wiobuf[3*WRIOBSZ];
1427c478bd9Sstevel@tonic-gate static int Riocnt[2] = {0, 0};
1437c478bd9Sstevel@tonic-gate static char *Riop[2];
1447c478bd9Sstevel@tonic-gate static char *Wiop[3];
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate extern int optind;		/* variable in getopt() */
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate extern char
1497c478bd9Sstevel@tonic-gate 	*optarg;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate static struct call Cucall;	/* call structure for altconn()	*/
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate static int Saved_tty;		/* was TCGETAW of _Tv0 successful?	*/
1547c478bd9Sstevel@tonic-gate static int Saved_termios;	/* was TCGETSW of _Tv0 successful?	*/
1557c478bd9Sstevel@tonic-gate static struct termio _Tv, _Tv0;	/* for saving, changing TTY atributes */
1567c478bd9Sstevel@tonic-gate static struct termios _Tv0s;	/* for saving, changing TTY atributes */
1577c478bd9Sstevel@tonic-gate static struct termio _Lv;	/* attributes for the line to remote */
1587c478bd9Sstevel@tonic-gate static struct termios _Lvs;	/* attributes for the line to remote */
1597c478bd9Sstevel@tonic-gate static char prompt[BUFSIZ]= "[";
1607c478bd9Sstevel@tonic-gate static struct utsname utsn;
1617c478bd9Sstevel@tonic-gate static int command_line_hups = 0;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate static char filename[BUFSIZ] = "/dev/null";
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate static char
1667c478bd9Sstevel@tonic-gate 	_Cxc,			/* place into which we do character io*/
1677c478bd9Sstevel@tonic-gate 	_Tintr,			/* current input INTR */
1687c478bd9Sstevel@tonic-gate 	_Tquit,			/* current input QUIT */
1697c478bd9Sstevel@tonic-gate 	_Terase,		/* current input ERASE */
1707c478bd9Sstevel@tonic-gate 	_Tkill,			/* current input KILL */
1717c478bd9Sstevel@tonic-gate 	_Teol,			/* current secondary input EOL */
1727c478bd9Sstevel@tonic-gate 	_Myeof,			/* current input EOF */
1737c478bd9Sstevel@tonic-gate 	term_mask,		/* mask value for local terminal */
1747c478bd9Sstevel@tonic-gate 	line_mask;		/* mask value for remote line */
1757c478bd9Sstevel@tonic-gate 				/* either '0177' or '0377' */
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate int
1787c478bd9Sstevel@tonic-gate 	Echoe,			/* save users ECHOE bit */
1797c478bd9Sstevel@tonic-gate 	Echok,			/* save users ECHOK bit */
1807c478bd9Sstevel@tonic-gate 	Intrupt=NO,		/* interrupt indicator */
1817c478bd9Sstevel@tonic-gate 	Ifc=YES,		/* NO means remote can't XON/XOFF */
1827c478bd9Sstevel@tonic-gate 	Ofc=YES,		/* NO means local can't XON/XOFF */
1837c478bd9Sstevel@tonic-gate 	Rtn_code=0,		/* default return code */
1847c478bd9Sstevel@tonic-gate 	Divert=NO,		/* don't allow unsolicited redirection */
1857c478bd9Sstevel@tonic-gate 	OldStyle=NO,		/* don't handle old '~>:filename' syntax */
1867c478bd9Sstevel@tonic-gate 				/* this will be mandatory in SVR4.1 */
1877c478bd9Sstevel@tonic-gate 	Takeflag=NO,		/* indicates a ~%take is in progress */
1887c478bd9Sstevel@tonic-gate 	Dologin=NO,		/* go through the login chat sequence */
1897c478bd9Sstevel@tonic-gate 	Docmd=NO;		/* execute command instead of interactive cu */
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate EXTERN int			/* These are initialized in line.c */
1927c478bd9Sstevel@tonic-gate 	Terminal,		/* flag; remote is a terminal */
1937c478bd9Sstevel@tonic-gate 	Oddflag,		/* flag- odd parity option*/
1947c478bd9Sstevel@tonic-gate 	Evenflag,		/* flag- even parity option*/
1957c478bd9Sstevel@tonic-gate 	Duplex,			/* Unix= full duplex=YES; half = NO */
1967c478bd9Sstevel@tonic-gate 	term_8bit,		/* is terminal set for 8 bit processing */
1977c478bd9Sstevel@tonic-gate 	line_8bit;		/* is line set for 8 bit processing */
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate EXTERN int clear_hup();
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate pid_t
2027c478bd9Sstevel@tonic-gate 	Child,			/* pid for receive process */
2037c478bd9Sstevel@tonic-gate 	Shell;			/* pid for escape process */
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate static pid_t
2067c478bd9Sstevel@tonic-gate 	dofork();		/* fork and return pid */
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate static int
2097c478bd9Sstevel@tonic-gate 	r_char(),		/* local io routine */
2107c478bd9Sstevel@tonic-gate 	w_char(),		/* local io routine */
2117c478bd9Sstevel@tonic-gate 	wioflsh();
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate static void
2147c478bd9Sstevel@tonic-gate 	_onintrpt(),		/* interrupt routines */
2157c478bd9Sstevel@tonic-gate 	_rcvdead(),
2167c478bd9Sstevel@tonic-gate 	_quit(),
2177c478bd9Sstevel@tonic-gate 	_bye();
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate extern void	cleanup();
2207c478bd9Sstevel@tonic-gate extern void	tdmp();
2217c478bd9Sstevel@tonic-gate extern int conn(), altconn(), transmit(), tilda();
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate static void
2247c478bd9Sstevel@tonic-gate 	recfork(),
2257c478bd9Sstevel@tonic-gate 	sysname(),
2267c478bd9Sstevel@tonic-gate 	blckcnt(),
2277c478bd9Sstevel@tonic-gate 	_flush(),
2287c478bd9Sstevel@tonic-gate 	_shell(),
2297c478bd9Sstevel@tonic-gate 	_dopercen(),
2307c478bd9Sstevel@tonic-gate 	_receive(),
2317c478bd9Sstevel@tonic-gate 	_mode(),
2327c478bd9Sstevel@tonic-gate 	_w_str();
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate extern char *Myline;	/* flag to force the requested line to be used  */
2357c478bd9Sstevel@tonic-gate extern char *Mytype;	/* flag to force requested line type to be used
2367c478bd9Sstevel@tonic-gate 			 * rddev() will compare the string to the D_TYPE
2377c478bd9Sstevel@tonic-gate 			 * (first) field of the Devices record and skip any
2387c478bd9Sstevel@tonic-gate 			 * records where they are not equal. Mytype is set
2397c478bd9Sstevel@tonic-gate 			 * to point to the argument of the -c option from
2407c478bd9Sstevel@tonic-gate 			 * the command line. */
2417c478bd9Sstevel@tonic-gate static char *P_USAGE= "Usage: %s [-dhtnLC] [-c device] [-s speed] [-l line] [-b 7|8]\n\t[-o | -e] telno | systemname [local-cmd]\n";
2427c478bd9Sstevel@tonic-gate static char *P_CON_FAILED = "Connect failed: %s\r\n";
2437c478bd9Sstevel@tonic-gate static char *P_Ct_OPEN = "Cannot open: %s\r\n";
2447c478bd9Sstevel@tonic-gate static char *P_LINE_GONE = "Remote line gone\r\n";
2457c478bd9Sstevel@tonic-gate static char *P_Ct_EXSH = "Can't execute shell\r\n";
2467c478bd9Sstevel@tonic-gate static char *P_Ct_DIVERT = "Can't divert to %s\r\n";
2477c478bd9Sstevel@tonic-gate static char *P_Ct_UNDIVERT = "Can't end diversion to %s\r\n";
2487c478bd9Sstevel@tonic-gate static char *P_Bad_DIVERT = "Won't divert to %s. Unsolicited.\r\n";
2497c478bd9Sstevel@tonic-gate static char *P_STARTWITH = "Use `~~' to start line with `~'\r\n";
2507c478bd9Sstevel@tonic-gate static char *P_CNTAFTER = "File transmission interrupted after %ld bytes.\r\n";
2517c478bd9Sstevel@tonic-gate static char *P_CNTLINES = "%d lines/";
2527c478bd9Sstevel@tonic-gate static char *P_CNTCHAR = "%ld characters\r\n";
2537c478bd9Sstevel@tonic-gate static char *P_FILEINTR = "File transmission interrupted\r\n";
2547c478bd9Sstevel@tonic-gate static char *P_Ct_FK = "Can't fork -- try later\r\n";
2557c478bd9Sstevel@tonic-gate static char *P_Ct_SPECIAL = "r\nCan't transmit special character `%#o'\r\n";
2567c478bd9Sstevel@tonic-gate static char *P_TOOLONG = "\nLine too long\r\n";
2577c478bd9Sstevel@tonic-gate static char *P_IOERR = "r\nIO error\r\n";
2587c478bd9Sstevel@tonic-gate static char *P_USECMD = "Use `~$'cmd \r\n";
2597c478bd9Sstevel@tonic-gate #ifdef forfutureuse
2607c478bd9Sstevel@tonic-gate static char *P_USEPLUSCMD ="Use `~+'cmd \r\n";
2617c478bd9Sstevel@tonic-gate #endif
2627c478bd9Sstevel@tonic-gate #ifdef u3b
2637c478bd9Sstevel@tonic-gate static char *P_NOTERMSTAT = "Can't get terminal status\r\n";
2647c478bd9Sstevel@tonic-gate static char *P_3BCONSOLE = "Sorry, you can't cu from a 3B console\r\n";
2657c478bd9Sstevel@tonic-gate #endif
2667c478bd9Sstevel@tonic-gate static char *P_TELLENGTH = "Telno cannot exceed 58 digits!\r\n";
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate /***************************************************************
2697c478bd9Sstevel@tonic-gate  *	main: get command line args, establish connection, and fork.
2707c478bd9Sstevel@tonic-gate  *	Child invokes "receive" to read from remote & write to TTY.
2717c478bd9Sstevel@tonic-gate  *	Main line invokes "transmit" to read TTY & write to remote.
2727c478bd9Sstevel@tonic-gate  ***************************************************************/
2737c478bd9Sstevel@tonic-gate 
274462be471Sceastha int
main(int argc,char * argv[])275*3b296559SToomas Soome main(int argc, char *argv[])
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate     extern void setservice();
2787c478bd9Sstevel@tonic-gate     extern int sysaccess();
2797c478bd9Sstevel@tonic-gate     char s[MAXPH];
2807c478bd9Sstevel@tonic-gate     char *string;
2817c478bd9Sstevel@tonic-gate     int i;
2827c478bd9Sstevel@tonic-gate     int errflag=0;
2837c478bd9Sstevel@tonic-gate     int lflag=0;
2847c478bd9Sstevel@tonic-gate     int nflag=0;
2857c478bd9Sstevel@tonic-gate     int systemname = 0;
2867c478bd9Sstevel@tonic-gate     char vdisable;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate     /* Set locale environment variables local definitions */
2897c478bd9Sstevel@tonic-gate     (void) setlocale(LC_ALL, "");
2907c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
2917c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it wasn't */
2927c478bd9Sstevel@tonic-gate #endif
2937c478bd9Sstevel@tonic-gate     (void) textdomain(TEXT_DOMAIN);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate     Riop[0] = &Riobuf[0];
2967c478bd9Sstevel@tonic-gate     Riop[1] = &Riobuf[WRIOBSZ];
2977c478bd9Sstevel@tonic-gate     Wiop[0] = &Wiobuf[0];
2987c478bd9Sstevel@tonic-gate     Wiop[1] = &Wiobuf[WRIOBSZ];
2997c478bd9Sstevel@tonic-gate     Wiop[2] = &Wiobuf[2*WRIOBSZ];
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate     Verbose = 1;		/*for uucp callers,  dialers feedback*/
3027c478bd9Sstevel@tonic-gate     if ((string = strrchr(argv[0], '/')) != NULL)
3037c478bd9Sstevel@tonic-gate 	string++;
3047c478bd9Sstevel@tonic-gate     else
3057c478bd9Sstevel@tonic-gate 	string = argv[0];
3067c478bd9Sstevel@tonic-gate     if (strlcpy(Progname, string, NAMESIZE) >= NAMESIZE) {
3077c478bd9Sstevel@tonic-gate 	errno = ENAMETOOLONG;
3087c478bd9Sstevel@tonic-gate 	perror("cu");
3097c478bd9Sstevel@tonic-gate 	exit(1);
3107c478bd9Sstevel@tonic-gate     }
3117c478bd9Sstevel@tonic-gate     setservice(Progname);
3127c478bd9Sstevel@tonic-gate     if ( sysaccess(EACCESS_SYSTEMS) != 0 ) {
3137c478bd9Sstevel@tonic-gate 	(void)fprintf(stderr,
3147c478bd9Sstevel@tonic-gate 	     gettext("%s: Cannot read Systems files\n"), Progname);
3157c478bd9Sstevel@tonic-gate 	exit(1);
3167c478bd9Sstevel@tonic-gate     }
3177c478bd9Sstevel@tonic-gate     if ( sysaccess(EACCESS_DEVICES) != 0 ) {
3187c478bd9Sstevel@tonic-gate 	(void)fprintf(stderr,
3197c478bd9Sstevel@tonic-gate 	     gettext("%s: Cannot read Devices files\n"), Progname);
3207c478bd9Sstevel@tonic-gate 	exit(1);
3217c478bd9Sstevel@tonic-gate     }
3227c478bd9Sstevel@tonic-gate     if ( sysaccess(EACCESS_DIALERS) != 0 ) {
3237c478bd9Sstevel@tonic-gate 	(void)fprintf(stderr,
3247c478bd9Sstevel@tonic-gate 	    gettext("%s: Cannot read Dialers files\n"), Progname);
3257c478bd9Sstevel@tonic-gate 	exit(1);
3267c478bd9Sstevel@tonic-gate     }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate     Cucall.speed = "Any";	/*default speed*/
3297c478bd9Sstevel@tonic-gate     Cucall.line = CNULL;
3307c478bd9Sstevel@tonic-gate     Cucall.telno = CNULL;
3317c478bd9Sstevel@tonic-gate     Cucall.type = CNULL;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate /*Flags for -h, -t, -e, and -o options set here; corresponding line attributes*/
3347c478bd9Sstevel@tonic-gate /*are set in fixline() in culine.c before remote connection is made	   */
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate     while((i = getopt(argc, argv, "dhteons:l:c:b:LCH")) != EOF)
3377c478bd9Sstevel@tonic-gate 	switch(i) {
3387c478bd9Sstevel@tonic-gate 	    case 'd':
3397c478bd9Sstevel@tonic-gate 		Debug = 9; /*turns on uucp debugging-level 9*/
3407c478bd9Sstevel@tonic-gate 		break;
3417c478bd9Sstevel@tonic-gate 	    case 'h':
3427c478bd9Sstevel@tonic-gate 		Duplex  = NO;
3437c478bd9Sstevel@tonic-gate 		Ifc = NO;
3447c478bd9Sstevel@tonic-gate 		Ofc = NO;
3457c478bd9Sstevel@tonic-gate 		break;
3467c478bd9Sstevel@tonic-gate 	    case 't':
3477c478bd9Sstevel@tonic-gate 		Terminal = YES;
3487c478bd9Sstevel@tonic-gate 		break;
3497c478bd9Sstevel@tonic-gate 	    case 'e':
3507c478bd9Sstevel@tonic-gate 		if ( Oddflag ) {
3517c478bd9Sstevel@tonic-gate 		    (void)fprintf(stderr,
3527c478bd9Sstevel@tonic-gate 			gettext("%s: Cannot have both even and odd parity\n"),
3537c478bd9Sstevel@tonic-gate 			argv[0]);
3547c478bd9Sstevel@tonic-gate 		    exit(1);
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 		Evenflag = 1;
3577c478bd9Sstevel@tonic-gate 		break;
3587c478bd9Sstevel@tonic-gate 	    case 'o':
3597c478bd9Sstevel@tonic-gate 		if ( Evenflag ) {
3607c478bd9Sstevel@tonic-gate 		    (void)fprintf(stderr,
3617c478bd9Sstevel@tonic-gate 			gettext("%s: Cannot have both even and odd parity\n"),
3627c478bd9Sstevel@tonic-gate 			argv[0]);
3637c478bd9Sstevel@tonic-gate 		    exit(1);
3647c478bd9Sstevel@tonic-gate 		}
3657c478bd9Sstevel@tonic-gate 		Oddflag = 1;
3667c478bd9Sstevel@tonic-gate 		break;
3677c478bd9Sstevel@tonic-gate 	    case 'n':
3687c478bd9Sstevel@tonic-gate 		nflag++;
3697c478bd9Sstevel@tonic-gate 		printf(gettext("Please enter the number: "));
3707c478bd9Sstevel@tonic-gate 		/* Read line from stdin, remove trailing newline, if any */
3717c478bd9Sstevel@tonic-gate 		if (fgets(s, sizeof(s), stdin) != NULL &&
3727c478bd9Sstevel@tonic-gate 			strchr(s, '\n') != NULL)
3737c478bd9Sstevel@tonic-gate 		   s[strlen(s)-1] = '\0';
3747c478bd9Sstevel@tonic-gate 		break;
3757c478bd9Sstevel@tonic-gate 	    case 's':
3767c478bd9Sstevel@tonic-gate 		Sflag++;
3777c478bd9Sstevel@tonic-gate 		Cucall.speed = optarg;
3787c478bd9Sstevel@tonic-gate 		break;
3797c478bd9Sstevel@tonic-gate 	    case 'l':
3807c478bd9Sstevel@tonic-gate 		lflag++;
3817c478bd9Sstevel@tonic-gate 		Cucall.line = optarg;
3827c478bd9Sstevel@tonic-gate 		break;
3837c478bd9Sstevel@tonic-gate 	    case 'c':
3847c478bd9Sstevel@tonic-gate 		Cucall.type = optarg;
3857c478bd9Sstevel@tonic-gate 		Mytype = optarg;
3867c478bd9Sstevel@tonic-gate 		break;
3877c478bd9Sstevel@tonic-gate 	    case 'b':
3887c478bd9Sstevel@tonic-gate 		line_8bit = ((*optarg=='7') ? NO : ((*optarg=='8') ? YES : -1));
3897c478bd9Sstevel@tonic-gate 		if ( line_8bit == -1 ) {
3907c478bd9Sstevel@tonic-gate 		    (void) fprintf(stderr,
3917c478bd9Sstevel@tonic-gate 			gettext("%s: b option value must be '7' or '8'\n"),
3927c478bd9Sstevel@tonic-gate 			argv[0]);
3937c478bd9Sstevel@tonic-gate 		    exit(1);
3947c478bd9Sstevel@tonic-gate 		}
3957c478bd9Sstevel@tonic-gate 		break;
3967c478bd9Sstevel@tonic-gate 	    case 'L':
3977c478bd9Sstevel@tonic-gate 		Dologin++;
3987c478bd9Sstevel@tonic-gate 		break;
3997c478bd9Sstevel@tonic-gate 	    case 'C':
4007c478bd9Sstevel@tonic-gate 		Docmd++;
4017c478bd9Sstevel@tonic-gate 		break;
4027c478bd9Sstevel@tonic-gate 	    case 'H':
4037c478bd9Sstevel@tonic-gate 		command_line_hups++;
4047c478bd9Sstevel@tonic-gate 		break;
4057c478bd9Sstevel@tonic-gate 	    case '?':
4067c478bd9Sstevel@tonic-gate 		++errflag;
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate #ifdef  u3b
4107c478bd9Sstevel@tonic-gate     {
4117c478bd9Sstevel@tonic-gate     struct stat buff;
4127c478bd9Sstevel@tonic-gate     if(fstat(TTYIN, &buff) < 0) {
4137c478bd9Sstevel@tonic-gate 	VERBOSE(gettext(P_NOTERMSTAT),"");
4147c478bd9Sstevel@tonic-gate 	exit(1);
4157c478bd9Sstevel@tonic-gate     } else if ( (buff.st_mode & S_IFMT) == S_IFCHR && buff.st_rdev == 0 ) {
4167c478bd9Sstevel@tonic-gate 	VERBOSE(gettext(P_3BCONSOLE),"");
4177c478bd9Sstevel@tonic-gate 	exit(1);
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate     }
4207c478bd9Sstevel@tonic-gate #endif
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate     if((optind < argc && optind > 0) || (nflag && optind > 0)) {
4237c478bd9Sstevel@tonic-gate 	if(nflag)
4247c478bd9Sstevel@tonic-gate 	    string=s;
4257c478bd9Sstevel@tonic-gate 	else
4267c478bd9Sstevel@tonic-gate 	    string = strdup(argv[optind++]);
4277c478bd9Sstevel@tonic-gate 	Cucall.telno = string;
4287c478bd9Sstevel@tonic-gate 	if ( strlen(string) != strspn(string, "0123456789=-*#") ) {
4297c478bd9Sstevel@tonic-gate 	    /* if it's not a legitimate telno, then it should be a systemname */
4307c478bd9Sstevel@tonic-gate 	    if ( nflag ) {
4317c478bd9Sstevel@tonic-gate 		(void)fprintf(stderr, gettext("%s: Bad phone number %s\n"),
4327c478bd9Sstevel@tonic-gate 				argv[0], string);
4337c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Phone numbers may contain "
4347c478bd9Sstevel@tonic-gate 		    "only the digits 0 through 9 and the special\n"
4357c478bd9Sstevel@tonic-gate 		    "characters =, -, * and #.\n"));
4367c478bd9Sstevel@tonic-gate 		exit(1);
4377c478bd9Sstevel@tonic-gate 	    }
4387c478bd9Sstevel@tonic-gate 	    systemname++;
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate     } else
4417c478bd9Sstevel@tonic-gate 	if(Cucall.line == CNULL)   /*if none of above, must be direct */
4427c478bd9Sstevel@tonic-gate 	    ++errflag;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate     if(errflag) {
4457c478bd9Sstevel@tonic-gate 	VERBOSE(gettext(P_USAGE), argv[0]);
4467c478bd9Sstevel@tonic-gate 	exit(1);
4477c478bd9Sstevel@tonic-gate     }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate     if ((Cucall.telno != CNULL) &&
4507c478bd9Sstevel@tonic-gate 		(strlen(Cucall.telno) >= (size_t)(MAXPH - 1))) {
4517c478bd9Sstevel@tonic-gate 	VERBOSE(gettext(P_TELLENGTH),"");
4527c478bd9Sstevel@tonic-gate 	exit(0);
4537c478bd9Sstevel@tonic-gate     }
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate     /* save initial tty state */
4567c478bd9Sstevel@tonic-gate     if (!(Saved_termios = ( ioctl(TTYIN, TCGETS, &_Tv0s) >= 0 ))) {
4577c478bd9Sstevel@tonic-gate 	Saved_tty = ( ioctl(TTYIN, TCGETA, &_Tv0) == 0 );
4587c478bd9Sstevel@tonic-gate 	_Tv0s.c_lflag = _Tv0.c_lflag;
4597c478bd9Sstevel@tonic-gate 	_Tv0s.c_oflag = _Tv0.c_oflag;
4607c478bd9Sstevel@tonic-gate 	_Tv0s.c_iflag = _Tv0.c_iflag;
4617c478bd9Sstevel@tonic-gate 	_Tv0s.c_cflag = _Tv0.c_cflag;
4627c478bd9Sstevel@tonic-gate 	for(i = 0; i < NCC; i++)
4637c478bd9Sstevel@tonic-gate 		_Tv0s.c_cc[i] = _Tv0.c_cc[i];
4647c478bd9Sstevel@tonic-gate     }
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate     if (Saved_termios || Saved_tty) {
4677c478bd9Sstevel@tonic-gate 	char *p;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	/*
4707c478bd9Sstevel@tonic-gate 	 * We consider the terminal to be in 8 bit mode only if cs8 is set,
4717c478bd9Sstevel@tonic-gate 	 * istrip is not set, and we're not in the "C" locale.  The "C"
4727c478bd9Sstevel@tonic-gate 	 * locale is by definition 7 bit only.  This provides reasonable
4737c478bd9Sstevel@tonic-gate 	 * compatibility when running in the "C" locale (currently the default)
4747c478bd9Sstevel@tonic-gate 	 * and connecting to other systems, which are most often 7 bit systems.
4757c478bd9Sstevel@tonic-gate 	 */
4767c478bd9Sstevel@tonic-gate 	term_8bit = ( (_Tv0s.c_cflag & CS8) && !(_Tv0s.c_iflag & ISTRIP) &&
4777c478bd9Sstevel@tonic-gate 	  ((p = setlocale(LC_CTYPE, NULL)) != NULL) && (strcmp(p, "C") != 0) );
4787c478bd9Sstevel@tonic-gate 	if ( !Oddflag && !Evenflag )
4797c478bd9Sstevel@tonic-gate 	    if (_Tv0s.c_cflag & PARENB)
4807c478bd9Sstevel@tonic-gate 		if (_Tv0s.c_cflag & PARODD)
4817c478bd9Sstevel@tonic-gate 		    Oddflag = 1;
4827c478bd9Sstevel@tonic-gate 		else
4837c478bd9Sstevel@tonic-gate 		    Evenflag = 1;
4847c478bd9Sstevel@tonic-gate     }
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate     if (line_8bit == -1)
4877c478bd9Sstevel@tonic-gate 	line_8bit = term_8bit;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate     term_mask = ( term_8bit ? 0377 : 0177 );
4907c478bd9Sstevel@tonic-gate     line_mask = ( line_8bit ? 0377 : 0177 );
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate     /* if not set, use the POSIX disabled designation */
4937c478bd9Sstevel@tonic-gate #ifdef _POSIX_VDISABLE
4947c478bd9Sstevel@tonic-gate     vdisable = _POSIX_VDISABLE;
4957c478bd9Sstevel@tonic-gate #else
4967c478bd9Sstevel@tonic-gate     vdisable = fpathconf(TTYIN, _PC_VDISABLE);
4977c478bd9Sstevel@tonic-gate #endif
4987c478bd9Sstevel@tonic-gate     _Tintr = _Tv0s.c_cc[VINTR] ? _Tv0s.c_cc[VINTR] : vdisable;
4997c478bd9Sstevel@tonic-gate     _Tquit = _Tv0s.c_cc[VQUIT] ? _Tv0s.c_cc[VQUIT] : vdisable;
5007c478bd9Sstevel@tonic-gate     _Terase = _Tv0s.c_cc[VERASE] ? _Tv0s.c_cc[VERASE] : vdisable;
5017c478bd9Sstevel@tonic-gate     _Tkill = _Tv0s.c_cc[VKILL] ? _Tv0s.c_cc[VKILL] : vdisable;
5027c478bd9Sstevel@tonic-gate     _Teol = _Tv0s.c_cc[VEOL] ? _Tv0s.c_cc[VEOL] : vdisable;
5037c478bd9Sstevel@tonic-gate     _Myeof = _Tv0s.c_cc[VEOF] ? _Tv0s.c_cc[VEOF] : '\04';
5047c478bd9Sstevel@tonic-gate     Echoe = _Tv0s.c_lflag & ECHOE;
5057c478bd9Sstevel@tonic-gate     Echok = _Tv0s.c_lflag & ECHOK;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate     (void)signal(SIGHUP, cleanup);
5087c478bd9Sstevel@tonic-gate     (void)signal(SIGQUIT, cleanup);
5097c478bd9Sstevel@tonic-gate     (void)signal(SIGINT, cleanup);
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate /* place call to system; if "cu systemname", use conn() from uucp
5127c478bd9Sstevel@tonic-gate    directly.  Otherwise, use altconn() which dummies in the
5137c478bd9Sstevel@tonic-gate    Systems file line.
5147c478bd9Sstevel@tonic-gate */
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate     if(systemname) {
5177c478bd9Sstevel@tonic-gate 	if ( lflag )
5187c478bd9Sstevel@tonic-gate 	    (void)fprintf(stderr,
5197c478bd9Sstevel@tonic-gate 	        gettext("%s: Warning: -l flag ignored when system name used\n"),
5207c478bd9Sstevel@tonic-gate 	        argv[0]);
5217c478bd9Sstevel@tonic-gate 	if ( Sflag )
5227c478bd9Sstevel@tonic-gate 	    (void)fprintf(stderr,
5237c478bd9Sstevel@tonic-gate 	        gettext("%s: Warning: -s flag ignored when system name used\n"),
5247c478bd9Sstevel@tonic-gate 	        argv[0]);
5257c478bd9Sstevel@tonic-gate 	Cn = conn(string);
5267c478bd9Sstevel@tonic-gate 	if ( (Cn < 0) && (Cucall.type != CNULL) )
5277c478bd9Sstevel@tonic-gate 	    Cn = altconn(&Cucall);
5287c478bd9Sstevel@tonic-gate     } else
5297c478bd9Sstevel@tonic-gate 	Cn = altconn(&Cucall);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate     if(Cn < 0) {
5327c478bd9Sstevel@tonic-gate 	VERBOSE(gettext(P_CON_FAILED),UERRORTEXT);
5337c478bd9Sstevel@tonic-gate 	cleanup(-Cn);
5347c478bd9Sstevel@tonic-gate     } else {
5357c478bd9Sstevel@tonic-gate 	struct stat Cnsbuf;
5367c478bd9Sstevel@tonic-gate 	if ( fstat(Cn, &Cnsbuf) == 0 )
5377c478bd9Sstevel@tonic-gate 	    Dev_mode = Cnsbuf.st_mode;
5387c478bd9Sstevel@tonic-gate 	else
5397c478bd9Sstevel@tonic-gate 	    Dev_mode = R_DEVICEMODE;
5407c478bd9Sstevel@tonic-gate 	fchmod(Cn, M_DEVICEMODE);
5417c478bd9Sstevel@tonic-gate     }
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate     if ((Docmd) && (argv[optind] == NULL)) {
5447c478bd9Sstevel@tonic-gate         (void) fprintf(stderr,gettext("cu: local cmd is required, -C is ignored.\n"));
5457c478bd9Sstevel@tonic-gate         VERBOSE(gettext(P_USAGE), argv[0]);
5467c478bd9Sstevel@tonic-gate         Docmd=NO;
5477c478bd9Sstevel@tonic-gate     }
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate     if (!Docmd) {
5507c478bd9Sstevel@tonic-gate 	Euid = geteuid();
5517c478bd9Sstevel@tonic-gate 	if((setuid(getuid()) < 0) || (setgid(getgid()) < 0)) {
5527c478bd9Sstevel@tonic-gate 	    VERBOSE("Unable to setuid/gid\n%s", "");
5537c478bd9Sstevel@tonic-gate 	    cleanup(101);
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate     }
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate     if(Debug)
5587c478bd9Sstevel@tonic-gate 	tdmp(Cn);
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate     /* At this point succeeded in getting an open communication line	*/
5617c478bd9Sstevel@tonic-gate     /* Conn() takes care of closing the Systems file			*/
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate     if (!Docmd) {
5647c478bd9Sstevel@tonic-gate 	(void)signal(SIGINT,_onintrpt);
5657c478bd9Sstevel@tonic-gate 	_mode(1);			/* put terminal in `raw' mode */
5667c478bd9Sstevel@tonic-gate 	VERBOSE("Connected\007\r\n%s", "");	/*bell!*/
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	/* must catch signals before fork.  if not and if _receive()	*/
5697c478bd9Sstevel@tonic-gate 	/* fails in just the right (wrong?) way, _rcvdead() can be	*/
5707c478bd9Sstevel@tonic-gate 	/* called and do "kill(getppid(),SIGUSR1);" before parent	*/
5717c478bd9Sstevel@tonic-gate 	/* has done calls to signal() after recfork().			*/
5727c478bd9Sstevel@tonic-gate 	(void)signal(SIGUSR1, _bye);
5737c478bd9Sstevel@tonic-gate 	(void)signal(SIGHUP, cleanup);
5747c478bd9Sstevel@tonic-gate 	(void)signal(SIGQUIT, _onintrpt);
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	sysname(&prompt[1]);	/* set up system name prompt */
5777c478bd9Sstevel@tonic-gate 	(void) strcat(prompt, "]");
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	recfork();		/* checks for child == 0 */
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	if(Child > 0) {
5827c478bd9Sstevel@tonic-gate 	    /*
5837c478bd9Sstevel@tonic-gate 	     * Because the child counts hangups for the -H flag,
5847c478bd9Sstevel@tonic-gate 	     * and because we fork a new child when doing (e.g.)
5857c478bd9Sstevel@tonic-gate 	     * ~%take, we assume the first child we fork has
5867c478bd9Sstevel@tonic-gate 	     * processed all the hangups and we reset the count here.
5877c478bd9Sstevel@tonic-gate 	     * We really should pass the remaining count back from
5887c478bd9Sstevel@tonic-gate 	     * the child to the parent when we kill the child.
5897c478bd9Sstevel@tonic-gate 	     */
5907c478bd9Sstevel@tonic-gate 	    command_line_hups = 0;
5917c478bd9Sstevel@tonic-gate 	    Rtn_code = transmit();
5927c478bd9Sstevel@tonic-gate 	    _quit(Rtn_code);
5937c478bd9Sstevel@tonic-gate 	    /*NOTREACHED*/
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate     } else {
5967c478bd9Sstevel@tonic-gate 	/*
5977c478bd9Sstevel@tonic-gate 	 * Fork a child to run the specified command,
5987c478bd9Sstevel@tonic-gate 	 * wait for it to finish, and clean up.
5997c478bd9Sstevel@tonic-gate 	 */
6007c478bd9Sstevel@tonic-gate 	Child = dofork();
6017c478bd9Sstevel@tonic-gate 	if (Child == 0) {
6027c478bd9Sstevel@tonic-gate 	    close(0);
6037c478bd9Sstevel@tonic-gate 	    close(1);
6047c478bd9Sstevel@tonic-gate 	    dup(Cn);
6057c478bd9Sstevel@tonic-gate 	    dup(Cn);
6067c478bd9Sstevel@tonic-gate 	    close(Cn);
6077c478bd9Sstevel@tonic-gate 	    setgid(getgid());
6087c478bd9Sstevel@tonic-gate 	    setuid(getuid());
6097c478bd9Sstevel@tonic-gate 	    execvp(argv[optind], &argv[optind]);
6107c478bd9Sstevel@tonic-gate 	    exit(-1);
6117c478bd9Sstevel@tonic-gate 	    /* NOTREACHED */
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 	wait(0);
6147c478bd9Sstevel@tonic-gate 	/* XXX - should return wait status as our exit code */
6157c478bd9Sstevel@tonic-gate     }
6167c478bd9Sstevel@tonic-gate     cleanup(Cn);
6177c478bd9Sstevel@tonic-gate     /*NOTREACHED*/
618462be471Sceastha 	return (0);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate /*
6227c478bd9Sstevel@tonic-gate  *	Kill the present child, if it exists, then fork a new one.
6237c478bd9Sstevel@tonic-gate  */
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate static void
recfork(void)626*3b296559SToomas Soome recfork(void)
6277c478bd9Sstevel@tonic-gate {
6287c478bd9Sstevel@tonic-gate     int ret, status;
6297c478bd9Sstevel@tonic-gate     if (Child) {
6307c478bd9Sstevel@tonic-gate 	kill(Child, SIGKILL);
6317c478bd9Sstevel@tonic-gate 	while ( (ret = wait(&status)) != Child )
6327c478bd9Sstevel@tonic-gate 	    if (ret == -1 && errno != EINTR)
6337c478bd9Sstevel@tonic-gate 		break;
6347c478bd9Sstevel@tonic-gate     }
6357c478bd9Sstevel@tonic-gate     Child = dofork();
6367c478bd9Sstevel@tonic-gate     if(Child == 0) {
6377c478bd9Sstevel@tonic-gate 	(void)signal(SIGUSR1, SIG_DFL);
6387c478bd9Sstevel@tonic-gate 	(void)signal(SIGHUP, _rcvdead);
6397c478bd9Sstevel@tonic-gate 	(void)signal(SIGQUIT, SIG_IGN);
6407c478bd9Sstevel@tonic-gate 	(void)signal(SIGINT, SIG_IGN);
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	_receive();	/* This should run until killed */
6437c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
6447c478bd9Sstevel@tonic-gate     }
6457c478bd9Sstevel@tonic-gate     return;
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate /***************************************************************
6497c478bd9Sstevel@tonic-gate  *	transmit: copy stdin to remote fd, except:
6507c478bd9Sstevel@tonic-gate  *	~.	terminate
6517c478bd9Sstevel@tonic-gate  *	~!	local login-style shell
6527c478bd9Sstevel@tonic-gate  *	~!cmd	execute cmd locally
6537c478bd9Sstevel@tonic-gate  *	~$proc	execute proc locally, send output to line
6547c478bd9Sstevel@tonic-gate  *	~%cmd	execute builtin cmd (put, take, or break)
6557c478bd9Sstevel@tonic-gate  ****************************************************************/
6567c478bd9Sstevel@tonic-gate #ifdef forfutureuse
6577c478bd9Sstevel@tonic-gate  /*****************************************************************
6587c478bd9Sstevel@tonic-gate   *	~+proc	execute locally, with stdout to and stdin from line.
6597c478bd9Sstevel@tonic-gate   ******************************************************************/
6607c478bd9Sstevel@tonic-gate #endif
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate int
transmit(void)663*3b296559SToomas Soome transmit(void)
6647c478bd9Sstevel@tonic-gate {
6657c478bd9Sstevel@tonic-gate     char b[BUFSIZ];
666462be471Sceastha     char *p;
667462be471Sceastha     int escape;
668462be471Sceastha     int id = 0;  /* flag for systemname prompt on tilda escape */
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate     CDEBUG(4,"transmit started\n\r%s", "");
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate     /* In main loop, always waiting to read characters from	*/
6737c478bd9Sstevel@tonic-gate     /* keyboard; writes characters to remote, or to TTYOUT	*/
6747c478bd9Sstevel@tonic-gate     /* on a tilda escape					*/
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate     for (;;) {
6777c478bd9Sstevel@tonic-gate 	p = b;
6787c478bd9Sstevel@tonic-gate 	while(r_char(TTYIN) == YES) {
6797c478bd9Sstevel@tonic-gate 	    if(p == b)  	/* Escape on leading  ~    */
6807c478bd9Sstevel@tonic-gate 		escape = (_Cxc == '~');
6817c478bd9Sstevel@tonic-gate 	    if(p == b+1)   	/* But not on leading ~~   */
6827c478bd9Sstevel@tonic-gate 		escape &= (_Cxc != '~');
6837c478bd9Sstevel@tonic-gate 	    if(escape) {
6847c478bd9Sstevel@tonic-gate 		 if(_Cxc == '\n' || _Cxc == '\r' || _Cxc == _Teol) {
6857c478bd9Sstevel@tonic-gate 		    *p = '\0';
6867c478bd9Sstevel@tonic-gate 		    if(tilda(b+1) == YES)
6877c478bd9Sstevel@tonic-gate 			return(0);
6887c478bd9Sstevel@tonic-gate 		    id = 0;
6897c478bd9Sstevel@tonic-gate 		    break;
6907c478bd9Sstevel@tonic-gate 		}
6917c478bd9Sstevel@tonic-gate 		if(_Cxc == _Tintr || _Cxc == _Tkill || _Cxc == _Tquit ||
6927c478bd9Sstevel@tonic-gate 			(Intrupt && _Cxc == '\0')) {
6937c478bd9Sstevel@tonic-gate 		    if(_Cxc == _Tkill) {
6947c478bd9Sstevel@tonic-gate 			if(Echok)
6957c478bd9Sstevel@tonic-gate 			    VERBOSE("\r\n%s", "");
6967c478bd9Sstevel@tonic-gate 		    } else {
6977c478bd9Sstevel@tonic-gate 			_Cxc = '\r';
6987c478bd9Sstevel@tonic-gate 			if( w_char(Cn) == NO) {
6997c478bd9Sstevel@tonic-gate 			    VERBOSE(gettext(P_LINE_GONE),"");
7007c478bd9Sstevel@tonic-gate 			    return(IOERR);
7017c478bd9Sstevel@tonic-gate 			}
7027c478bd9Sstevel@tonic-gate 			id=0;
7037c478bd9Sstevel@tonic-gate 		    }
7047c478bd9Sstevel@tonic-gate 		    break;
7057c478bd9Sstevel@tonic-gate 		}
7067c478bd9Sstevel@tonic-gate 		if((p == b+1) && (_Cxc != _Terase) && (!id)) {
7077c478bd9Sstevel@tonic-gate 		    id = 1;
7087c478bd9Sstevel@tonic-gate 		    VERBOSE("%s", prompt);
7097c478bd9Sstevel@tonic-gate 		}
7107c478bd9Sstevel@tonic-gate 		if(_Cxc == _Terase) {
7117c478bd9Sstevel@tonic-gate 		    p = (--p < b)? b:p;
7127c478bd9Sstevel@tonic-gate 		    if(p > b)
7137c478bd9Sstevel@tonic-gate 			if(Echoe) {
7147c478bd9Sstevel@tonic-gate 			    VERBOSE("\b \b%s", "");
7157c478bd9Sstevel@tonic-gate 			} else
7167c478bd9Sstevel@tonic-gate 			    (void)w_char(TTYOUT);
7177c478bd9Sstevel@tonic-gate 		} else {
7187c478bd9Sstevel@tonic-gate 		    (void)w_char(TTYOUT);
7197c478bd9Sstevel@tonic-gate 		    if(p-b < BUFSIZ)
7207c478bd9Sstevel@tonic-gate 			*p++ = _Cxc;
7217c478bd9Sstevel@tonic-gate 		    else {
7227c478bd9Sstevel@tonic-gate 			VERBOSE(gettext(P_TOOLONG),"");
7237c478bd9Sstevel@tonic-gate 			break;
7247c478bd9Sstevel@tonic-gate 		    }
7257c478bd9Sstevel@tonic-gate 		}
7267c478bd9Sstevel@tonic-gate     /*not a tilda escape command*/
7277c478bd9Sstevel@tonic-gate 	    } else {
7287c478bd9Sstevel@tonic-gate 		if(Intrupt && _Cxc == '\0') {
7297c478bd9Sstevel@tonic-gate 		    CDEBUG(4,"got break in transmit\n\r%s", "");
7307c478bd9Sstevel@tonic-gate 		    Intrupt = NO;
7317c478bd9Sstevel@tonic-gate 		    (*genbrk)(Cn);
7327c478bd9Sstevel@tonic-gate 		    _flush();
7337c478bd9Sstevel@tonic-gate 		    break;
7347c478bd9Sstevel@tonic-gate 		}
7357c478bd9Sstevel@tonic-gate 		if(w_char(Cn) == NO) {
7367c478bd9Sstevel@tonic-gate 		    VERBOSE(gettext(P_LINE_GONE),"");
7377c478bd9Sstevel@tonic-gate 		    return(IOERR);
7387c478bd9Sstevel@tonic-gate 		}
7397c478bd9Sstevel@tonic-gate 		if(Duplex == NO) {
7407c478bd9Sstevel@tonic-gate 		    if((w_char(TTYERR) == NO) || (wioflsh(TTYERR) == NO))
7417c478bd9Sstevel@tonic-gate 			return(IOERR);
7427c478bd9Sstevel@tonic-gate 		}
7437c478bd9Sstevel@tonic-gate 		if ((_Cxc == _Tintr) || (_Cxc == _Tquit) ||
7447c478bd9Sstevel@tonic-gate 		     ( (p==b) && (_Cxc == _Myeof) ) ) {
7457c478bd9Sstevel@tonic-gate 		    CDEBUG(4,"got a tintr\n\r%s", "");
7467c478bd9Sstevel@tonic-gate 		    _flush();
7477c478bd9Sstevel@tonic-gate 		    break;
7487c478bd9Sstevel@tonic-gate 		}
7497c478bd9Sstevel@tonic-gate 		if(_Cxc == '\n' || _Cxc == '\r' ||
7507c478bd9Sstevel@tonic-gate 		    _Cxc == _Teol || _Cxc == _Tkill) {
7517c478bd9Sstevel@tonic-gate 		    id=0;
7527c478bd9Sstevel@tonic-gate 		    Takeflag = NO;
7537c478bd9Sstevel@tonic-gate 		    break;
7547c478bd9Sstevel@tonic-gate 		}
7557c478bd9Sstevel@tonic-gate 		p = (char*)0;
7567c478bd9Sstevel@tonic-gate 	    }
7577c478bd9Sstevel@tonic-gate 	}
7587c478bd9Sstevel@tonic-gate     }
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate /***************************************************************
7627c478bd9Sstevel@tonic-gate  *	routine to halt input from remote and flush buffers
7637c478bd9Sstevel@tonic-gate  ***************************************************************/
7647c478bd9Sstevel@tonic-gate static void
_flush(void)765*3b296559SToomas Soome _flush(void)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate     (void)ioctl(TTYOUT, TCXONC, 0);	/* stop tty output */
7687c478bd9Sstevel@tonic-gate     (void)ioctl(Cn, TCFLSH, 0);		/* flush remote input */
7697c478bd9Sstevel@tonic-gate     (void)ioctl(TTYOUT, TCFLSH, 1);	/* flush tty output */
7707c478bd9Sstevel@tonic-gate     (void)ioctl(TTYOUT, TCXONC, 1);	/* restart tty output */
7717c478bd9Sstevel@tonic-gate     if(Takeflag == NO) {
7727c478bd9Sstevel@tonic-gate 	return;		/* didn't interupt file transmission */
7737c478bd9Sstevel@tonic-gate     }
7747c478bd9Sstevel@tonic-gate     VERBOSE(gettext(P_FILEINTR),"");
7757c478bd9Sstevel@tonic-gate     (void)sleep(3);
7767c478bd9Sstevel@tonic-gate     _w_str("echo '\n~>\n';mesg y;stty echo\n");
7777c478bd9Sstevel@tonic-gate     Takeflag = NO;
7787c478bd9Sstevel@tonic-gate     return;
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate /**************************************************************
7827c478bd9Sstevel@tonic-gate  *	command interpreter for escape lines
7837c478bd9Sstevel@tonic-gate  **************************************************************/
7847c478bd9Sstevel@tonic-gate int
tilda(cmd)7857c478bd9Sstevel@tonic-gate tilda(cmd)
786462be471Sceastha char	*cmd;
7877c478bd9Sstevel@tonic-gate {
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate     VERBOSE("\r\n%s", "");
7907c478bd9Sstevel@tonic-gate     CDEBUG(4,"call tilda(%s)\r\n", cmd);
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate     switch(cmd[0]) {
7937c478bd9Sstevel@tonic-gate 	case CSUSP:
7947c478bd9Sstevel@tonic-gate 	case CDSUSP:
7957c478bd9Sstevel@tonic-gate 	    _mode(0);
7967c478bd9Sstevel@tonic-gate 	    kill(cmd[0] == CDSUSP ? getpid() : (pid_t) 0, SIGTSTP);
7977c478bd9Sstevel@tonic-gate 	    _mode(1);
7987c478bd9Sstevel@tonic-gate 	    break;
7997c478bd9Sstevel@tonic-gate 	case '.':
8007c478bd9Sstevel@tonic-gate 	    if(Cucall.telno == CNULL)
8017c478bd9Sstevel@tonic-gate 		if(cmd[1] != '.') {
8027c478bd9Sstevel@tonic-gate 		    _w_str("\04\04\04\04\04");
8037c478bd9Sstevel@tonic-gate 		    if (Child)
8047c478bd9Sstevel@tonic-gate 			kill(Child, SIGKILL);
8057c478bd9Sstevel@tonic-gate 		    if (ioctl (Cn, TCGETS, &_Lvs) < 0) {
8067c478bd9Sstevel@tonic-gate 		    	(void) ioctl (Cn, TCGETA, &_Lv);
8077c478bd9Sstevel@tonic-gate 		    	/* speed to zero for hangup */
8087c478bd9Sstevel@tonic-gate 		    	_Lv.c_cflag = 0;
8097c478bd9Sstevel@tonic-gate 		    	(void) ioctl (Cn, TCSETAW, &_Lv);
8107c478bd9Sstevel@tonic-gate 		    } else {
8117c478bd9Sstevel@tonic-gate 		    	/* speed to zero for hangup */
8127c478bd9Sstevel@tonic-gate 			_Lvs.c_cflag &= 0xffff0000;
8137c478bd9Sstevel@tonic-gate 			cfsetospeed(&_Lvs, B0);
8147c478bd9Sstevel@tonic-gate 		    	(void) ioctl (Cn, TCSETSW, &_Lvs);
8157c478bd9Sstevel@tonic-gate 		    }
8167c478bd9Sstevel@tonic-gate 		    (void) sleep (2);
8177c478bd9Sstevel@tonic-gate 		}
8187c478bd9Sstevel@tonic-gate 	    return(YES);
8197c478bd9Sstevel@tonic-gate 	case '!':
8207c478bd9Sstevel@tonic-gate 	    _shell(cmd);	/* local shell */
8217c478bd9Sstevel@tonic-gate 	    VERBOSE("\r%c\r\n", *cmd);
8227c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
8237c478bd9Sstevel@tonic-gate 	    break;
8247c478bd9Sstevel@tonic-gate 	case '$':
8257c478bd9Sstevel@tonic-gate 	    if(cmd[1] == '\0') {
8267c478bd9Sstevel@tonic-gate 		VERBOSE(gettext(P_USECMD),"");
8277c478bd9Sstevel@tonic-gate 		VERBOSE("(continue)%s", "");
8287c478bd9Sstevel@tonic-gate 	    } else {
8297c478bd9Sstevel@tonic-gate 		_shell(cmd);	/*Local shell  */
8307c478bd9Sstevel@tonic-gate 		VERBOSE("\r%c\r\n", *cmd);
8317c478bd9Sstevel@tonic-gate 	    }
8327c478bd9Sstevel@tonic-gate 	    break;
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate #ifdef forfutureuse
8357c478bd9Sstevel@tonic-gate 	case '+':
8367c478bd9Sstevel@tonic-gate 	    if(cmd[1] == '\0') {
8377c478bd9Sstevel@tonic-gate 		VERBOSE(gettext(P_USEPLUSCMD), "");
8387c478bd9Sstevel@tonic-gate 		VERBOSE("(continue)%s", "");
8397c478bd9Sstevel@tonic-gate 	    } else {
8407c478bd9Sstevel@tonic-gate 		if (*cmd == '+')
8417c478bd9Sstevel@tonic-gate 			  /* must suspend receive to give*/
8427c478bd9Sstevel@tonic-gate 			  /*remote out to stdin of cmd */
8437c478bd9Sstevel@tonic-gate 		    kill(Child, SIGKILL);
8447c478bd9Sstevel@tonic-gate 		    _shell(cmd);	/* Local shell */
8457c478bd9Sstevel@tonic-gate 		if (*cmd == '+')
8467c478bd9Sstevel@tonic-gate 		    recfork();
8477c478bd9Sstevel@tonic-gate 		VERBOSE("\r%c\r\n", *cmd);
8487c478bd9Sstevel@tonic-gate 	    }
8497c478bd9Sstevel@tonic-gate 	    break;
8507c478bd9Sstevel@tonic-gate #endif
8517c478bd9Sstevel@tonic-gate 	case '%':
8527c478bd9Sstevel@tonic-gate 	    _dopercen(++cmd);
8537c478bd9Sstevel@tonic-gate 	    break;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	case 't':
8567c478bd9Sstevel@tonic-gate 	    tdmp(TTYIN);
8577c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
8587c478bd9Sstevel@tonic-gate 	    break;
8597c478bd9Sstevel@tonic-gate 	case 'l':
8607c478bd9Sstevel@tonic-gate 	    tdmp(Cn);
8617c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
8627c478bd9Sstevel@tonic-gate 	    break;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	default:
8657c478bd9Sstevel@tonic-gate 	    VERBOSE(gettext(P_STARTWITH),"");
8667c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
8677c478bd9Sstevel@tonic-gate 	    break;
8687c478bd9Sstevel@tonic-gate     }
8697c478bd9Sstevel@tonic-gate     return(NO);
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate /***************************************************************
8737c478bd9Sstevel@tonic-gate  *	The routine "shell" takes an argument starting with
8747c478bd9Sstevel@tonic-gate  *	either "!" or "$", and terminated with '\0'.
8757c478bd9Sstevel@tonic-gate  *	If $arg, arg is the name of a local shell file which
8767c478bd9Sstevel@tonic-gate  *	is executed and its output is passed to the remote.
8777c478bd9Sstevel@tonic-gate  *	If !arg, we escape to a local shell to execute arg
8787c478bd9Sstevel@tonic-gate  *	with output to TTY, and if arg is null, escape to
8797c478bd9Sstevel@tonic-gate  *	a local shell and blind the remote line.  In either
8807c478bd9Sstevel@tonic-gate  *	case, '^D' will kill the escape status.
8817c478bd9Sstevel@tonic-gate  **************************************************************/
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate #ifdef forfutureuse
8847c478bd9Sstevel@tonic-gate /***************************************************************
8857c478bd9Sstevel@tonic-gate  *	Another argument to the routine "shell" may be +.  If +arg,
8867c478bd9Sstevel@tonic-gate  *	arg is the name of a local shell file which is executed with
8877c478bd9Sstevel@tonic-gate  *	stdin from and stdout to the remote.
8887c478bd9Sstevel@tonic-gate  **************************************************************/
8897c478bd9Sstevel@tonic-gate #endif
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate static void
_shell(char * str)892*3b296559SToomas Soome _shell(char *str)
8937c478bd9Sstevel@tonic-gate {
8947c478bd9Sstevel@tonic-gate     pid_t	fk, w_ret;
8957c478bd9Sstevel@tonic-gate     void	(*xx)(), (*yy)();
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate     CDEBUG(4,"call _shell(%s)\r\n", str);
8987c478bd9Sstevel@tonic-gate     fk = dofork();
8997c478bd9Sstevel@tonic-gate     if(fk < 0)
9007c478bd9Sstevel@tonic-gate 	return;
9017c478bd9Sstevel@tonic-gate     Shell = fk;
9027c478bd9Sstevel@tonic-gate     _mode(0);	/* restore normal tty attributes */
9037c478bd9Sstevel@tonic-gate     xx = signal(SIGINT, SIG_IGN);
9047c478bd9Sstevel@tonic-gate     yy = signal(SIGQUIT, SIG_IGN);
9057c478bd9Sstevel@tonic-gate     if(fk == 0) {
9067c478bd9Sstevel@tonic-gate 	char *shell;
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	if( (shell = getenv("SHELL")) == NULL)
9097c478bd9Sstevel@tonic-gate 	    /* use default if user's shell is not set */
9107c478bd9Sstevel@tonic-gate 	    shell = SHELL;
9117c478bd9Sstevel@tonic-gate 	(void)close(TTYOUT);
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 	/***********************************************
9147c478bd9Sstevel@tonic-gate 	 * Hook-up our "standard output"
9157c478bd9Sstevel@tonic-gate 	 * to either the tty for '!' or the line
9167c478bd9Sstevel@tonic-gate 	 * for '$'  as appropriate
9177c478bd9Sstevel@tonic-gate 	 ***********************************************/
9187c478bd9Sstevel@tonic-gate #ifdef forfutureuse
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	/************************************************
9217c478bd9Sstevel@tonic-gate 	 * Or to the line for '+'.
9227c478bd9Sstevel@tonic-gate 	 **********************************************/
9237c478bd9Sstevel@tonic-gate #endif
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	(void)fcntl((*str == '!')? TTYERR:Cn,F_DUPFD,TTYOUT);
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate #ifdef forfutureuse
9287c478bd9Sstevel@tonic-gate 	/*************************************************
9297c478bd9Sstevel@tonic-gate 	 * Hook-up "standard input" to the line for '+'.
9307c478bd9Sstevel@tonic-gate 	 * **********************************************/
9317c478bd9Sstevel@tonic-gate 	if (*str == '+') {
9327c478bd9Sstevel@tonic-gate 	    (void)close(TTYIN);
9337c478bd9Sstevel@tonic-gate 	    (void)fcntl(Cn,F_DUPFD,TTYIN);
9347c478bd9Sstevel@tonic-gate 	    }
9357c478bd9Sstevel@tonic-gate #endif
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	/***********************************************
9387c478bd9Sstevel@tonic-gate 	 * Hook-up our "standard input"
9397c478bd9Sstevel@tonic-gate 	 * to the tty for '!' and '$'.
9407c478bd9Sstevel@tonic-gate 	 ***********************************************/
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	(void)close(Cn);   	/*parent still has Cn*/
9437c478bd9Sstevel@tonic-gate 	(void)signal(SIGINT, SIG_DFL);
9447c478bd9Sstevel@tonic-gate 	(void)signal(SIGHUP, SIG_DFL);
9457c478bd9Sstevel@tonic-gate 	(void)signal(SIGQUIT, SIG_DFL);
9467c478bd9Sstevel@tonic-gate 	(void)signal(SIGUSR1, SIG_DFL);
9477c478bd9Sstevel@tonic-gate 	if(*++str == '\0')
9487c478bd9Sstevel@tonic-gate 	    (void)execl(shell,shell,(char*) 0,(char*) 0,(char *) 0);
9497c478bd9Sstevel@tonic-gate 	else
9507c478bd9Sstevel@tonic-gate 	    (void)execl(shell,"sh","-c",str,(char *) 0);
9517c478bd9Sstevel@tonic-gate 	VERBOSE(gettext(P_Ct_EXSH),"");
9527c478bd9Sstevel@tonic-gate 	exit(0);
9537c478bd9Sstevel@tonic-gate     }
9547c478bd9Sstevel@tonic-gate     while ((w_ret = wait((int*)0)) != fk)
9557c478bd9Sstevel@tonic-gate 	if (w_ret == -1 && errno != EINTR)
9567c478bd9Sstevel@tonic-gate 	    break;
9577c478bd9Sstevel@tonic-gate     Shell = 0;
9587c478bd9Sstevel@tonic-gate     (void)signal(SIGINT, xx);
9597c478bd9Sstevel@tonic-gate     (void)signal(SIGQUIT, yy);
9607c478bd9Sstevel@tonic-gate     _mode(1);
9617c478bd9Sstevel@tonic-gate     return;
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate /***************************************************************
9667c478bd9Sstevel@tonic-gate  *	This function implements the 'put', 'take', 'break',
9677c478bd9Sstevel@tonic-gate  *	'ifc' (aliased to nostop) and 'ofc' (aliased to noostop)
9687c478bd9Sstevel@tonic-gate  *	commands which are internal to cu.
9697c478bd9Sstevel@tonic-gate  ***************************************************************/
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate static void
_dopercen(char * cmd)972*3b296559SToomas Soome _dopercen(char *cmd)
9737c478bd9Sstevel@tonic-gate {
9747c478bd9Sstevel@tonic-gate     char	*arg[5];
9757c478bd9Sstevel@tonic-gate     char	*getpath;
9767c478bd9Sstevel@tonic-gate     char	mypath[MAXPATH];
9777c478bd9Sstevel@tonic-gate     int	narg;
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate     blckcnt((long)(-1));
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate     CDEBUG(4,"call _dopercen(\"%s\")\r\n", cmd);
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate     arg[narg=0] = strtok(cmd, " \t\n");
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate     /* following loop breaks out the command and args */
9867c478bd9Sstevel@tonic-gate     while((arg[++narg] = strtok((char*) NULL, " \t\n")) != NULL) {
9877c478bd9Sstevel@tonic-gate 	if(narg < 4)
9887c478bd9Sstevel@tonic-gate 	    continue;
9897c478bd9Sstevel@tonic-gate 	else
9907c478bd9Sstevel@tonic-gate 	    break;
9917c478bd9Sstevel@tonic-gate     }
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate     /* ~%take file option */
9947c478bd9Sstevel@tonic-gate     if(EQUALS(arg[0], "take")) {
9957c478bd9Sstevel@tonic-gate 	if(narg < 2 || narg > 3) {
9967c478bd9Sstevel@tonic-gate 	    VERBOSE("usage: ~%%take from [to]\r\n%s", "");
9977c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
9987c478bd9Sstevel@tonic-gate 	    return;
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 	if(narg == 2)
10017c478bd9Sstevel@tonic-gate 	    arg[2] = arg[1];
10027c478bd9Sstevel@tonic-gate 	(void) strcpy(filename, arg[2]);
10037c478bd9Sstevel@tonic-gate 	recfork();	/* fork so child (receive) knows filename */
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	/*
10067c478bd9Sstevel@tonic-gate 	 * be sure that the remote file (arg[1]) exists before
10077c478bd9Sstevel@tonic-gate 	 * you try to take it.   otherwise, the error message from
10087c478bd9Sstevel@tonic-gate 	 * cat will wind up in the local file (arg[2])
10097c478bd9Sstevel@tonic-gate 	 *
10107c478bd9Sstevel@tonic-gate 	 * what we're doing is:
10117c478bd9Sstevel@tonic-gate 	 *	stty -echo; \
10127c478bd9Sstevel@tonic-gate 	 *	if test -r arg1
10137c478bd9Sstevel@tonic-gate 	 *	then (echo '~[local]'>arg2; cat arg1; echo '~[local]'>)
10147c478bd9Sstevel@tonic-gate 	 *	else echo can't open: arg1
10157c478bd9Sstevel@tonic-gate 	 *	fi; \
10167c478bd9Sstevel@tonic-gate 	 *	stty echo
10177c478bd9Sstevel@tonic-gate 	 *
10187c478bd9Sstevel@tonic-gate 	 */
10197c478bd9Sstevel@tonic-gate 	_w_str("stty -echo;if test -r ");
10207c478bd9Sstevel@tonic-gate 	_w_str(arg[1]);
10217c478bd9Sstevel@tonic-gate 	_w_str("; then (echo '~");
10227c478bd9Sstevel@tonic-gate 	_w_str(prompt);
10237c478bd9Sstevel@tonic-gate 	_w_str(">'");
10247c478bd9Sstevel@tonic-gate 	_w_str(arg[2]);
10257c478bd9Sstevel@tonic-gate 	_w_str(";cat ");
10267c478bd9Sstevel@tonic-gate 	_w_str(arg[1]);
10277c478bd9Sstevel@tonic-gate 	_w_str(";echo '~");
10287c478bd9Sstevel@tonic-gate 	_w_str(prompt);
10297c478bd9Sstevel@tonic-gate 	_w_str(">'); else echo cant\\'t open: ");
10307c478bd9Sstevel@tonic-gate 	_w_str(arg[1]);
10317c478bd9Sstevel@tonic-gate 	_w_str("; fi;stty echo\n");
10327c478bd9Sstevel@tonic-gate 	Takeflag = YES;
10337c478bd9Sstevel@tonic-gate 	return;
10347c478bd9Sstevel@tonic-gate     }
10357c478bd9Sstevel@tonic-gate     /* ~%put file option*/
10367c478bd9Sstevel@tonic-gate     if(EQUALS(arg[0], "put")) {
10377c478bd9Sstevel@tonic-gate 	FILE	*file;
10387c478bd9Sstevel@tonic-gate 	char	ch, buf[BUFSIZ], spec[NCC+1], *b, *p, *q;
10397c478bd9Sstevel@tonic-gate 	int	i, j, len, tc=0, lines=0;
10407c478bd9Sstevel@tonic-gate 	long	chars=0L;
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	if(narg < 2 || narg > 3) {
10437c478bd9Sstevel@tonic-gate 	    VERBOSE("usage: ~%%put from [to]\r\n%s", "");
10447c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
10457c478bd9Sstevel@tonic-gate 	    return;
10467c478bd9Sstevel@tonic-gate 	}
10477c478bd9Sstevel@tonic-gate 	if(narg == 2)
10487c478bd9Sstevel@tonic-gate 	    arg[2] = arg[1];
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	if((file = fopen(arg[1], "r")) == NULL) {
10517c478bd9Sstevel@tonic-gate 	    VERBOSE(gettext(P_Ct_OPEN), arg[1]);
10527c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
10537c478bd9Sstevel@tonic-gate 	    return;
10547c478bd9Sstevel@tonic-gate 	}
10557c478bd9Sstevel@tonic-gate 	/*
10567c478bd9Sstevel@tonic-gate 	 * if cannot write into file on remote machine, write into
10577c478bd9Sstevel@tonic-gate 	 * /dev/null
10587c478bd9Sstevel@tonic-gate 	 *
10597c478bd9Sstevel@tonic-gate 	 * what we're doing is:
10607c478bd9Sstevel@tonic-gate 	 *	stty -echo
10617c478bd9Sstevel@tonic-gate 	 *	(cat - > arg2) || cat - > /dev/null
10627c478bd9Sstevel@tonic-gate 	 *	stty echo
10637c478bd9Sstevel@tonic-gate 	 */
10647c478bd9Sstevel@tonic-gate 	_w_str("stty -echo;(cat - >");
10657c478bd9Sstevel@tonic-gate 	_w_str(arg[2]);
10667c478bd9Sstevel@tonic-gate 	_w_str(")||cat - >/dev/null;stty echo\n");
10677c478bd9Sstevel@tonic-gate 	Intrupt = NO;
10687c478bd9Sstevel@tonic-gate 	for(i=0,j=0; i < NCC; ++i)
10697c478bd9Sstevel@tonic-gate 	    if((ch=_Tv0s.c_cc[i]) != '\0')
10707c478bd9Sstevel@tonic-gate 		spec[j++] = ch;
10717c478bd9Sstevel@tonic-gate 	spec[j] = '\0';
10727c478bd9Sstevel@tonic-gate 	_mode(2);	/*accept interrupts from keyboard*/
10737c478bd9Sstevel@tonic-gate 	(void)sleep(5);	/*hope that w_str info digested*/
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 	/* Read characters line by line into buf to write to	*/
10767c478bd9Sstevel@tonic-gate 	/* remote with character and line count for blckcnt	*/
10777c478bd9Sstevel@tonic-gate 	while(Intrupt == NO &&
10787c478bd9Sstevel@tonic-gate 		fgets(b= &buf[MID],MID,file) != NULL) {
10797c478bd9Sstevel@tonic-gate 	    /* worse case is each char must be escaped*/
10807c478bd9Sstevel@tonic-gate 	    len = strlen(b);
10817c478bd9Sstevel@tonic-gate 	    chars += len;		/* character count */
10827c478bd9Sstevel@tonic-gate 	    p = b;
10837c478bd9Sstevel@tonic-gate 	    while(q = strpbrk(p, spec)) {
10847c478bd9Sstevel@tonic-gate 		if(*q == _Tintr || *q == _Tquit || *q == _Teol) {
10857c478bd9Sstevel@tonic-gate 		    VERBOSE(gettext(P_Ct_SPECIAL), *q);
10867c478bd9Sstevel@tonic-gate 		    (void)strcpy(q, q+1);
10877c478bd9Sstevel@tonic-gate 		    Intrupt = YES;
10887c478bd9Sstevel@tonic-gate 		} else {
10897c478bd9Sstevel@tonic-gate 		    b = strncpy(b-1, b, q-b);
10907c478bd9Sstevel@tonic-gate 		    *(q-1) = '\\';
10917c478bd9Sstevel@tonic-gate 		}
10927c478bd9Sstevel@tonic-gate 		p = q+1;
10937c478bd9Sstevel@tonic-gate 	    }
10947c478bd9Sstevel@tonic-gate 	    if((tc += len) >= MID) {
10957c478bd9Sstevel@tonic-gate 		(void)sleep(1);
10967c478bd9Sstevel@tonic-gate 		tc = len;
10977c478bd9Sstevel@tonic-gate 	    }
10987c478bd9Sstevel@tonic-gate 	    if(write(Cn, b, (unsigned)strlen(b)) < 0) {
10997c478bd9Sstevel@tonic-gate 		VERBOSE(gettext(P_IOERR),"");
11007c478bd9Sstevel@tonic-gate 		Intrupt = YES;
11017c478bd9Sstevel@tonic-gate 		break;
11027c478bd9Sstevel@tonic-gate 	    }
11037c478bd9Sstevel@tonic-gate 	    ++lines;		/* line count */
11047c478bd9Sstevel@tonic-gate 	    blckcnt((long)chars);
11057c478bd9Sstevel@tonic-gate 	}
11067c478bd9Sstevel@tonic-gate 	_mode(1);
11077c478bd9Sstevel@tonic-gate 	blckcnt((long)(-2));		/* close */
11087c478bd9Sstevel@tonic-gate 	(void)fclose(file);
11097c478bd9Sstevel@tonic-gate 	if(Intrupt == YES) {
11107c478bd9Sstevel@tonic-gate 	    Intrupt = NO;
11117c478bd9Sstevel@tonic-gate 	    _w_str("\n");
11127c478bd9Sstevel@tonic-gate 	    VERBOSE(gettext(P_CNTAFTER), ++chars);
11137c478bd9Sstevel@tonic-gate 	} else {
11147c478bd9Sstevel@tonic-gate 	    VERBOSE(gettext(P_CNTLINES), lines);
11157c478bd9Sstevel@tonic-gate 	    VERBOSE(gettext(P_CNTCHAR),chars);
11167c478bd9Sstevel@tonic-gate 	}
11177c478bd9Sstevel@tonic-gate 	(void)sleep(3);
11187c478bd9Sstevel@tonic-gate 	_w_str("\04");
11197c478bd9Sstevel@tonic-gate 	return;
11207c478bd9Sstevel@tonic-gate     }
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 	/*  ~%b or ~%break  */
11237c478bd9Sstevel@tonic-gate     if(EQUALS(arg[0], "b") || EQUALS(arg[0], "break")) {
11247c478bd9Sstevel@tonic-gate 	(*genbrk)(Cn);
11257c478bd9Sstevel@tonic-gate 	return;
11267c478bd9Sstevel@tonic-gate     }
11277c478bd9Sstevel@tonic-gate 	/*  ~%d or ~%debug toggle  */
11287c478bd9Sstevel@tonic-gate     if(EQUALS(arg[0], "d") || EQUALS(arg[0], "debug")) {
11297c478bd9Sstevel@tonic-gate 	if(Debug == 0)
11307c478bd9Sstevel@tonic-gate 	    Debug = 9;
11317c478bd9Sstevel@tonic-gate 	else
11327c478bd9Sstevel@tonic-gate 	    Debug = 0;
11337c478bd9Sstevel@tonic-gate 	VERBOSE("(continue)%s", "");
11347c478bd9Sstevel@tonic-gate 	return;
11357c478bd9Sstevel@tonic-gate     }
11367c478bd9Sstevel@tonic-gate 	/*  ~%[ifc|nostop]  toggles start/stop input control  */
11377c478bd9Sstevel@tonic-gate     if( EQUALS(arg[0], "ifc") || EQUALS(arg[0], "nostop") ) {
11387c478bd9Sstevel@tonic-gate 	(void)ioctl(Cn, TCGETA, &_Tv);
11397c478bd9Sstevel@tonic-gate 	Ifc = !Ifc;
11407c478bd9Sstevel@tonic-gate 	if(Ifc == YES)
11417c478bd9Sstevel@tonic-gate 	    _Tv.c_iflag |= IXOFF;
11427c478bd9Sstevel@tonic-gate 	else
11437c478bd9Sstevel@tonic-gate 	    _Tv.c_iflag &= ~IXOFF;
11447c478bd9Sstevel@tonic-gate 	(void)ioctl(Cn, TCSETAW, &_Tv);
11457c478bd9Sstevel@tonic-gate 	_mode(1);
11467c478bd9Sstevel@tonic-gate 	VERBOSE("(ifc %s)", (Ifc ? "enabled" : "disabled"));
11477c478bd9Sstevel@tonic-gate 	VERBOSE("(continue)%s", "");
11487c478bd9Sstevel@tonic-gate 	return;
11497c478bd9Sstevel@tonic-gate     }
11507c478bd9Sstevel@tonic-gate 	/*  ~%[ofc|noostop]  toggles start/stop output control  */
11517c478bd9Sstevel@tonic-gate     if( EQUALS(arg[0], "ofc") || EQUALS(arg[0], "noostop") ) {
11527c478bd9Sstevel@tonic-gate 	(void)ioctl(Cn, TCGETA, &_Tv);
11537c478bd9Sstevel@tonic-gate 	Ofc = !Ofc;
11547c478bd9Sstevel@tonic-gate 	if(Ofc == YES)
11557c478bd9Sstevel@tonic-gate 	    _Tv.c_iflag |= IXON;
11567c478bd9Sstevel@tonic-gate 	else
11577c478bd9Sstevel@tonic-gate 	    _Tv.c_iflag &= ~IXON;
11587c478bd9Sstevel@tonic-gate 	(void)ioctl(Cn, TCSETAW, &_Tv);
11597c478bd9Sstevel@tonic-gate 	_mode(1);
11607c478bd9Sstevel@tonic-gate 	VERBOSE("(ofc %s)", (Ofc ? "enabled" : "disabled"));
11617c478bd9Sstevel@tonic-gate 	VERBOSE("(continue)%s", "");
11627c478bd9Sstevel@tonic-gate 	return;
11637c478bd9Sstevel@tonic-gate     }
11647c478bd9Sstevel@tonic-gate 	/*  ~%divert toggles unsolicited redirection security */
11657c478bd9Sstevel@tonic-gate     if( EQUALS(arg[0], "divert") ) {
11667c478bd9Sstevel@tonic-gate 	Divert = !Divert;
11677c478bd9Sstevel@tonic-gate 	recfork();	/* fork a new child so it knows about change */
11687c478bd9Sstevel@tonic-gate 	VERBOSE("(unsolicited diversion %s)", (Divert ? "enabled" : "disabled"));
11697c478bd9Sstevel@tonic-gate 	VERBOSE("(continue)%s", "");
11707c478bd9Sstevel@tonic-gate 	return;
11717c478bd9Sstevel@tonic-gate     }
11727c478bd9Sstevel@tonic-gate 	/*  ~%old toggles recognition of old-style '~>:filename' */
11737c478bd9Sstevel@tonic-gate     if( EQUALS(arg[0], "old") ) {
11747c478bd9Sstevel@tonic-gate 	OldStyle = !OldStyle;
11757c478bd9Sstevel@tonic-gate 	recfork();	/* fork a new child so it knows about change */
11767c478bd9Sstevel@tonic-gate 	VERBOSE("(old-style diversion %s)", (OldStyle ? "enabled" : "disabled"));
11777c478bd9Sstevel@tonic-gate 	VERBOSE("(continue)%s", "");
11787c478bd9Sstevel@tonic-gate 	return;
11797c478bd9Sstevel@tonic-gate     }
11807c478bd9Sstevel@tonic-gate 	/* Change local current directory */
11817c478bd9Sstevel@tonic-gate     if(EQUALS(arg[0], "cd")) {
11827c478bd9Sstevel@tonic-gate 	if (narg < 2) {
11837c478bd9Sstevel@tonic-gate 	    getpath = getenv("HOME");
11847c478bd9Sstevel@tonic-gate 	    strlcpy(mypath, getpath, sizeof (mypath));
11857c478bd9Sstevel@tonic-gate 	    if(chdir(mypath) < 0) {
11867c478bd9Sstevel@tonic-gate 		VERBOSE("Cannot change to %s\r\n", mypath);
11877c478bd9Sstevel@tonic-gate 		VERBOSE("(continue)%s", "");
11887c478bd9Sstevel@tonic-gate 		return;
11897c478bd9Sstevel@tonic-gate 	    }
11907c478bd9Sstevel@tonic-gate 	} else if (chdir(arg[1]) < 0) {
11917c478bd9Sstevel@tonic-gate 	    VERBOSE("Cannot change to %s\r\n", arg[1]);
11927c478bd9Sstevel@tonic-gate 	    VERBOSE("(continue)%s", "");
11937c478bd9Sstevel@tonic-gate 	    return;
11947c478bd9Sstevel@tonic-gate 	}
11957c478bd9Sstevel@tonic-gate 	recfork();	/* fork a new child so it knows about change */
11967c478bd9Sstevel@tonic-gate 	VERBOSE("(continue)%s", "");
11977c478bd9Sstevel@tonic-gate 	return;
11987c478bd9Sstevel@tonic-gate     }
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate    if (arg[0] == (char *) NULL)
12017c478bd9Sstevel@tonic-gate        arg[0] = "";
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate     VERBOSE("~%%%s unknown to cu\r\n", arg[0]);
12047c478bd9Sstevel@tonic-gate     VERBOSE("(continue)%s", "");
12057c478bd9Sstevel@tonic-gate     return;
12067c478bd9Sstevel@tonic-gate }
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate /***************************************************************
12097c478bd9Sstevel@tonic-gate  *	receive: read from remote line, write to fd=1 (TTYOUT)
12107c478bd9Sstevel@tonic-gate  *	catch:
12117c478bd9Sstevel@tonic-gate  *	~>[>]:file
12127c478bd9Sstevel@tonic-gate  *	.
12137c478bd9Sstevel@tonic-gate  *	. stuff for file
12147c478bd9Sstevel@tonic-gate  *	.
12157c478bd9Sstevel@tonic-gate  *	~>	(ends diversion)
12167c478bd9Sstevel@tonic-gate  ***************************************************************/
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate static void
_receive(void)1219*3b296559SToomas Soome _receive(void)
12207c478bd9Sstevel@tonic-gate {
1221462be471Sceastha     int silent = NO, file = -1;
1222462be471Sceastha     char *p;
12237c478bd9Sstevel@tonic-gate     int	tic;
12247c478bd9Sstevel@tonic-gate     int for_me = NO;
12257c478bd9Sstevel@tonic-gate     char	b[BUFSIZ];
12267c478bd9Sstevel@tonic-gate     char	*b_p;
12277c478bd9Sstevel@tonic-gate     long	count;
12287c478bd9Sstevel@tonic-gate     int		line_ok = 1, rval;
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate     CDEBUG(4,"_receive started\r\n%s", "");
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate     b[0] = '\0';
12337c478bd9Sstevel@tonic-gate     b_p = p = b;
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate     while(line_ok) {
12367c478bd9Sstevel@tonic-gate 	rval = r_char(Cn);
12377c478bd9Sstevel@tonic-gate 	if (rval == NO) {
12387c478bd9Sstevel@tonic-gate 	    line_ok = 0;
12397c478bd9Sstevel@tonic-gate 	    continue;
12407c478bd9Sstevel@tonic-gate 	}
12417c478bd9Sstevel@tonic-gate 	if (rval == HUNGUP) {
12427c478bd9Sstevel@tonic-gate 	    if (command_line_hups > 0) {
12437c478bd9Sstevel@tonic-gate 		CDEBUG(4, "Ignoring device hangup\n%s", "");
12447c478bd9Sstevel@tonic-gate 		command_line_hups--;
12457c478bd9Sstevel@tonic-gate 		(void) setuid(Euid);	/* reacquire privileges */
12467c478bd9Sstevel@tonic-gate 		if (clear_hup(Cn) != SUCCESS) {
12477c478bd9Sstevel@tonic-gate 		    DEBUG(4, "Unable to clear hup on device\n%s", "");
12487c478bd9Sstevel@tonic-gate 		    line_ok = 0;
12497c478bd9Sstevel@tonic-gate 		}
12507c478bd9Sstevel@tonic-gate 		(void) setuid(getuid());  /* relinquish privileges */
12517c478bd9Sstevel@tonic-gate 	    } else
12527c478bd9Sstevel@tonic-gate 		line_ok = 0;
12537c478bd9Sstevel@tonic-gate 	    continue;
12547c478bd9Sstevel@tonic-gate 	}
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	if(silent == NO)    /* ie., if not redirecting from screen */
12577c478bd9Sstevel@tonic-gate 	    if(w_char(TTYOUT) == NO)
12587c478bd9Sstevel@tonic-gate 		_rcvdead(IOERR);    /* this will exit */
12597c478bd9Sstevel@tonic-gate 	/* remove CR's and fill inserted by remote */
12607c478bd9Sstevel@tonic-gate 	if(_Cxc == '\0' || _Cxc == RUB || _Cxc == '\r')
12617c478bd9Sstevel@tonic-gate 	    continue;
12627c478bd9Sstevel@tonic-gate 	*p++ = _Cxc;
12637c478bd9Sstevel@tonic-gate 	if(_Cxc != '\n' && (p-b) < BUFSIZ)
12647c478bd9Sstevel@tonic-gate 	    continue;
12657c478bd9Sstevel@tonic-gate 	/* ****************************************** */
12667c478bd9Sstevel@tonic-gate 	/* This code deals with ~%take file diversion */
12677c478bd9Sstevel@tonic-gate 	/* ****************************************** */
12687c478bd9Sstevel@tonic-gate 	if (b[0] == '~') {
12697c478bd9Sstevel@tonic-gate 	    int    append;
12707c478bd9Sstevel@tonic-gate 
12717c478bd9Sstevel@tonic-gate 	    if (EQUALSN(&b[1],prompt,strlen(prompt))) {
12727c478bd9Sstevel@tonic-gate 		b_p = b + 1 + strlen(prompt);
12737c478bd9Sstevel@tonic-gate 		for_me = YES;
12747c478bd9Sstevel@tonic-gate 	    } else {
12757c478bd9Sstevel@tonic-gate 		b_p = b + 1;
12767c478bd9Sstevel@tonic-gate 		for_me = NO;
12777c478bd9Sstevel@tonic-gate 	    }
12787c478bd9Sstevel@tonic-gate 	    if ( (for_me || OldStyle) && (*b_p == '>') ) {
12797c478bd9Sstevel@tonic-gate 		/* This is an acceptable '~[uname]>' line */
12807c478bd9Sstevel@tonic-gate 		b_p++;
12817c478bd9Sstevel@tonic-gate 		if ( (*b_p == '\n') && (silent == YES) ) {
12827c478bd9Sstevel@tonic-gate 		    /* end of diversion */
12837c478bd9Sstevel@tonic-gate 		    *b_p = '\0';
12847c478bd9Sstevel@tonic-gate 		    (void) strcpy(filename, "/dev/null");
12857c478bd9Sstevel@tonic-gate 		    if ( file >= 0 && close(file) ) {
12867c478bd9Sstevel@tonic-gate 			VERBOSE(gettext(P_Ct_UNDIVERT), b_p);
12877c478bd9Sstevel@tonic-gate 			perror(gettext("cu: close failed"));
12887c478bd9Sstevel@tonic-gate 			VERBOSE("%s","\r");
12897c478bd9Sstevel@tonic-gate 		    }
12907c478bd9Sstevel@tonic-gate 		    silent = NO;
12917c478bd9Sstevel@tonic-gate 		    blckcnt((long)(-2));
12927c478bd9Sstevel@tonic-gate 		    VERBOSE("%s\r\n", b);
12937c478bd9Sstevel@tonic-gate 		    VERBOSE(gettext(P_CNTLINES), tic);
12947c478bd9Sstevel@tonic-gate 		    VERBOSE(gettext(P_CNTCHAR), count);
12957c478bd9Sstevel@tonic-gate 		    file = -1;
12967c478bd9Sstevel@tonic-gate 		    p = b;
12977c478bd9Sstevel@tonic-gate 		    continue;
12987c478bd9Sstevel@tonic-gate 		} else if (*b_p != '\n') {
12997c478bd9Sstevel@tonic-gate 		    if ( *b_p == '>' ) {
13007c478bd9Sstevel@tonic-gate 			append = 1;
13017c478bd9Sstevel@tonic-gate 			b_p++;
13027c478bd9Sstevel@tonic-gate 		    }
13037c478bd9Sstevel@tonic-gate 		    if ( (for_me || (OldStyle && (*b_p == ':'))) && (silent == NO) ) {
13047c478bd9Sstevel@tonic-gate 			/* terminate filename string */
13057c478bd9Sstevel@tonic-gate 			*(p-1) = '\0';
13067c478bd9Sstevel@tonic-gate 			if ( *b_p == ':' )
13077c478bd9Sstevel@tonic-gate 			    b_p++;
13087c478bd9Sstevel@tonic-gate 			if ( !EQUALS(filename, b_p) ) {
13097c478bd9Sstevel@tonic-gate 			    if ( !Divert  || !EQUALS(filename, "/dev/null") ) {
13107c478bd9Sstevel@tonic-gate 				VERBOSE(gettext(P_Bad_DIVERT), b_p);
13117c478bd9Sstevel@tonic-gate 				(void) strcpy(filename, "/dev/null");
13127c478bd9Sstevel@tonic-gate 				append = 1;
13137c478bd9Sstevel@tonic-gate 			    } else {
13147c478bd9Sstevel@tonic-gate 				(void) strcpy(filename, b_p);
13157c478bd9Sstevel@tonic-gate 			    }
13167c478bd9Sstevel@tonic-gate 			}
13177c478bd9Sstevel@tonic-gate 			if ( append && ((file=open(filename,O_WRONLY)) >= 0) )
13187c478bd9Sstevel@tonic-gate 			    (void)lseek(file, 0L, 2);
13197c478bd9Sstevel@tonic-gate 			else
13207c478bd9Sstevel@tonic-gate 			    file = creat(filename, PUB_FILEMODE);
13217c478bd9Sstevel@tonic-gate 			if (file < 0) {
13227c478bd9Sstevel@tonic-gate 			    VERBOSE(gettext(P_Ct_DIVERT), filename);
13237c478bd9Sstevel@tonic-gate 			    perror(gettext("cu: open|creat failed"));
13247c478bd9Sstevel@tonic-gate 			    VERBOSE("%s","\r");
13257c478bd9Sstevel@tonic-gate 			    (void)sleep(5); /* 10 seemed too long*/
13267c478bd9Sstevel@tonic-gate 			}
13277c478bd9Sstevel@tonic-gate 			silent = YES;
13287c478bd9Sstevel@tonic-gate 			count = tic = 0;
13297c478bd9Sstevel@tonic-gate 			p = b;
13307c478bd9Sstevel@tonic-gate 			continue;
13317c478bd9Sstevel@tonic-gate 		    }
13327c478bd9Sstevel@tonic-gate 		}
13337c478bd9Sstevel@tonic-gate 	    }
13347c478bd9Sstevel@tonic-gate 	}
13357c478bd9Sstevel@tonic-gate 	/* Regular data, divert if appropriate */
13367c478bd9Sstevel@tonic-gate 	if ( silent == YES ) {
13377c478bd9Sstevel@tonic-gate 	    if ( file >= 0)
13387c478bd9Sstevel@tonic-gate 		(void)write(file, b, (unsigned)(p-b));
13397c478bd9Sstevel@tonic-gate 	    count += p-b;	/* tally char count */
13407c478bd9Sstevel@tonic-gate 	    ++tic;		/* tally lines */
13417c478bd9Sstevel@tonic-gate 	    blckcnt((long)count);
13427c478bd9Sstevel@tonic-gate 	}
13437c478bd9Sstevel@tonic-gate 	p = b;
13447c478bd9Sstevel@tonic-gate     }
13457c478bd9Sstevel@tonic-gate     /*
13467c478bd9Sstevel@tonic-gate      * we used to tell of lost carrier here, but now
13477c478bd9Sstevel@tonic-gate      * defer to _bye() so that escape processes are
13487c478bd9Sstevel@tonic-gate      * not interrupted.
13497c478bd9Sstevel@tonic-gate      */
13507c478bd9Sstevel@tonic-gate     _rcvdead(IOERR);
13517c478bd9Sstevel@tonic-gate     return;
13527c478bd9Sstevel@tonic-gate }
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate /***************************************************************
13557c478bd9Sstevel@tonic-gate  *	change the TTY attributes of the users terminal:
13567c478bd9Sstevel@tonic-gate  *	0 means restore attributes to pre-cu status.
13577c478bd9Sstevel@tonic-gate  *	1 means set `raw' mode for use during cu session.
13587c478bd9Sstevel@tonic-gate  *	2 means like 1 but accept interrupts from the keyboard.
13597c478bd9Sstevel@tonic-gate  ***************************************************************/
13607c478bd9Sstevel@tonic-gate static void
_mode(int arg)1361*3b296559SToomas Soome _mode(int arg)
13627c478bd9Sstevel@tonic-gate {
13637c478bd9Sstevel@tonic-gate     int i;
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate     CDEBUG(4,"call _mode(%d)\r\n", arg);
13667c478bd9Sstevel@tonic-gate     if(arg == 0) {
13677c478bd9Sstevel@tonic-gate 	if ( Saved_termios )
13687c478bd9Sstevel@tonic-gate 		(void)ioctl(TTYIN, TCSETSW, &_Tv0s);
13697c478bd9Sstevel@tonic-gate 	else if ( Saved_tty ) {
13707c478bd9Sstevel@tonic-gate 		_Tv0.c_lflag = _Tv0s.c_lflag;
13717c478bd9Sstevel@tonic-gate 		_Tv0.c_oflag = _Tv0s.c_oflag;
13727c478bd9Sstevel@tonic-gate 		_Tv0.c_iflag = _Tv0s.c_iflag;
13737c478bd9Sstevel@tonic-gate 		_Tv0.c_cflag = _Tv0s.c_cflag;
13747c478bd9Sstevel@tonic-gate 		for(i = 0; i < NCC; i++)
13757c478bd9Sstevel@tonic-gate 			_Tv0.c_cc[i] = _Tv0s.c_cc[i];
13767c478bd9Sstevel@tonic-gate 		(void)ioctl(TTYIN, TCSETAW, &_Tv0);
13777c478bd9Sstevel@tonic-gate 	}
13787c478bd9Sstevel@tonic-gate     } else {
13797c478bd9Sstevel@tonic-gate 	(void)ioctl(TTYIN, TCGETA, &_Tv);
13807c478bd9Sstevel@tonic-gate 	if(arg == 1) {
13817c478bd9Sstevel@tonic-gate 	    _Tv.c_iflag &= ~(INLCR | ICRNL | IGNCR | IUCLC);
13827c478bd9Sstevel@tonic-gate 	    if ( !term_8bit )
13837c478bd9Sstevel@tonic-gate 		_Tv.c_iflag |= ISTRIP;
13847c478bd9Sstevel@tonic-gate 	    _Tv.c_oflag |= OPOST;
13857c478bd9Sstevel@tonic-gate 	    _Tv.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET);
13867c478bd9Sstevel@tonic-gate 	    _Tv.c_lflag &= ~(ICANON | ISIG | ECHO);
13877c478bd9Sstevel@tonic-gate 	    if(Ifc == NO)
13887c478bd9Sstevel@tonic-gate 		_Tv.c_iflag &= ~IXON;
13897c478bd9Sstevel@tonic-gate 	    else
13907c478bd9Sstevel@tonic-gate 		_Tv.c_iflag |= IXON;
13917c478bd9Sstevel@tonic-gate 	    if(Ofc == NO)
13927c478bd9Sstevel@tonic-gate 		_Tv.c_iflag &= ~IXOFF;
13937c478bd9Sstevel@tonic-gate 	    else
13947c478bd9Sstevel@tonic-gate 		_Tv.c_iflag |= IXOFF;
13957c478bd9Sstevel@tonic-gate 	    if(Terminal) {
13967c478bd9Sstevel@tonic-gate 		_Tv.c_oflag |= ONLCR;
13977c478bd9Sstevel@tonic-gate 		_Tv.c_iflag |= ICRNL;
13987c478bd9Sstevel@tonic-gate 	    }
13997c478bd9Sstevel@tonic-gate 	    _Tv.c_cc[VEOF] = '\01';
14007c478bd9Sstevel@tonic-gate 	    _Tv.c_cc[VEOL] = '\0';
14017c478bd9Sstevel@tonic-gate 	}
14027c478bd9Sstevel@tonic-gate 	if(arg == 2) {
14037c478bd9Sstevel@tonic-gate 	    _Tv.c_iflag |= IXON;
14047c478bd9Sstevel@tonic-gate 	    _Tv.c_lflag |= ISIG;
14057c478bd9Sstevel@tonic-gate 	}
14067c478bd9Sstevel@tonic-gate 	(void)ioctl(TTYIN, TCSETAW, &_Tv);
14077c478bd9Sstevel@tonic-gate     }
14087c478bd9Sstevel@tonic-gate     return;
14097c478bd9Sstevel@tonic-gate }
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate static pid_t
dofork(void)1413*3b296559SToomas Soome dofork(void)
14147c478bd9Sstevel@tonic-gate {
1415462be471Sceastha     int i;
14167c478bd9Sstevel@tonic-gate     pid_t x;
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate     for(i = 0; i < 6; ++i) {
14197c478bd9Sstevel@tonic-gate 	if((x = fork()) >= 0) {
14207c478bd9Sstevel@tonic-gate 	    return(x);
14217c478bd9Sstevel@tonic-gate 	}
14227c478bd9Sstevel@tonic-gate     }
14237c478bd9Sstevel@tonic-gate 
14247c478bd9Sstevel@tonic-gate     if(Debug) perror("dofork");
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate     VERBOSE(gettext(P_Ct_FK),"");
14277c478bd9Sstevel@tonic-gate     return(x);
14287c478bd9Sstevel@tonic-gate }
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate static int
r_char(int fd)1431*3b296559SToomas Soome r_char(int fd)
14327c478bd9Sstevel@tonic-gate {
14337c478bd9Sstevel@tonic-gate     int rtn = 1, rfd;
14347c478bd9Sstevel@tonic-gate     char *riobuf;
14357c478bd9Sstevel@tonic-gate 
14367c478bd9Sstevel@tonic-gate     /* find starting pos in correct buffer in Riobuf	*/
14377c478bd9Sstevel@tonic-gate     rfd = RIOFD(fd);
14387c478bd9Sstevel@tonic-gate     riobuf = &Riobuf[rfd*WRIOBSZ];
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate     if (Riop[rfd] >= &riobuf[Riocnt[rfd]]) {
14417c478bd9Sstevel@tonic-gate 	/* empty read buffer - refill it	*/
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	/*	flush any waiting output	*/
14447c478bd9Sstevel@tonic-gate 	if ( (wioflsh(Cn) == NO ) || (wioflsh(TTYOUT) == NO) )
14457c478bd9Sstevel@tonic-gate 	    return(NO);
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate 	while((rtn = read(fd, riobuf, WRIOBSZ)) < 0){
14487c478bd9Sstevel@tonic-gate 	    if(errno == EINTR) {
14497c478bd9Sstevel@tonic-gate 		/* onintrpt() called asynchronously before this line */
14507c478bd9Sstevel@tonic-gate 		if(Intrupt == YES) {
14517c478bd9Sstevel@tonic-gate 		    /* got a BREAK */
14527c478bd9Sstevel@tonic-gate 		    _Cxc = '\0';
14537c478bd9Sstevel@tonic-gate 		    return(YES);
14547c478bd9Sstevel@tonic-gate 		} else {
14557c478bd9Sstevel@tonic-gate 		    /*a signal other than interrupt*/
14567c478bd9Sstevel@tonic-gate 		    /*received during read*/
14577c478bd9Sstevel@tonic-gate 		    continue;
14587c478bd9Sstevel@tonic-gate 		}
14597c478bd9Sstevel@tonic-gate 	    } else {
14607c478bd9Sstevel@tonic-gate 		CDEBUG(4,"got read error, not EINTR\n\r%s", "");
14617c478bd9Sstevel@tonic-gate 		break;			/* something wrong */
14627c478bd9Sstevel@tonic-gate 	    }
14637c478bd9Sstevel@tonic-gate 	}
14647c478bd9Sstevel@tonic-gate 	if (rtn > 0) {
14657c478bd9Sstevel@tonic-gate 	    /* reset current position in buffer	*/
14667c478bd9Sstevel@tonic-gate 	    /* and count of available chars		*/
14677c478bd9Sstevel@tonic-gate 	    Riop[rfd] = riobuf;
14687c478bd9Sstevel@tonic-gate 	    Riocnt[rfd] = rtn;
14697c478bd9Sstevel@tonic-gate 	}
14707c478bd9Sstevel@tonic-gate     }
14717c478bd9Sstevel@tonic-gate 
14727c478bd9Sstevel@tonic-gate     if ( rtn > 0 ) {
14737c478bd9Sstevel@tonic-gate 	_Cxc = *(Riop[rfd]++) & RMASK(fd);	/* mask off appropriate bits */
14747c478bd9Sstevel@tonic-gate 	return(YES);
14757c478bd9Sstevel@tonic-gate     } else if (rtn == 0) {
14767c478bd9Sstevel@tonic-gate 	_Cxc = '\0';
14777c478bd9Sstevel@tonic-gate 	return (HUNGUP);
14787c478bd9Sstevel@tonic-gate     } else {
14797c478bd9Sstevel@tonic-gate 	_Cxc = '\0';
14807c478bd9Sstevel@tonic-gate 	return(NO);
14817c478bd9Sstevel@tonic-gate     }
14827c478bd9Sstevel@tonic-gate }
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate static int
w_char(int fd)1485*3b296559SToomas Soome w_char(int fd)
14867c478bd9Sstevel@tonic-gate {
14877c478bd9Sstevel@tonic-gate     int wfd;
14887c478bd9Sstevel@tonic-gate     char *wiobuf;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate     /* find starting pos in correct buffer in Wiobuf	*/
14917c478bd9Sstevel@tonic-gate     wfd = WIOFD(fd);
14927c478bd9Sstevel@tonic-gate     wiobuf = &Wiobuf[wfd*WRIOBSZ];
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate     if (Wiop[wfd] >= &wiobuf[WRIOBSZ]) {
14957c478bd9Sstevel@tonic-gate 	/* full output buffer - flush it */
14967c478bd9Sstevel@tonic-gate 	if ( wioflsh(fd) == NO )
14977c478bd9Sstevel@tonic-gate 	    return(NO);
14987c478bd9Sstevel@tonic-gate     }
14997c478bd9Sstevel@tonic-gate     *(Wiop[wfd]++) = _Cxc & WMASK(fd);	/* mask off appropriate bits */
15007c478bd9Sstevel@tonic-gate     return(YES);
15017c478bd9Sstevel@tonic-gate }
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate /* wioflsh	flush output buffer	*/
15047c478bd9Sstevel@tonic-gate static int
wioflsh(int fd)1505*3b296559SToomas Soome wioflsh(int fd)
15067c478bd9Sstevel@tonic-gate {
15077c478bd9Sstevel@tonic-gate     int wfd;
15087c478bd9Sstevel@tonic-gate     char *wiobuf;
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate     /* find starting pos in correct buffer in Wiobuf	*/
15117c478bd9Sstevel@tonic-gate     wfd = WIOFD(fd);
15127c478bd9Sstevel@tonic-gate     wiobuf = &Wiobuf[wfd*WRIOBSZ];
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate     if (Wiop[wfd] > wiobuf) {
15157c478bd9Sstevel@tonic-gate 	/* there's something in the buffer */
15167c478bd9Sstevel@tonic-gate 	while(write(fd, wiobuf, (Wiop[wfd] - wiobuf)) < 0) {
15177c478bd9Sstevel@tonic-gate 	    if(errno == EINTR) {
15187c478bd9Sstevel@tonic-gate 		if(Intrupt == YES) {
15197c478bd9Sstevel@tonic-gate 		    VERBOSE("\ncu: Output blocked\r\n%s", "");
15207c478bd9Sstevel@tonic-gate 		    _quit(IOERR);
15217c478bd9Sstevel@tonic-gate 		} else
15227c478bd9Sstevel@tonic-gate 		    continue;	/* alarm went off */
15237c478bd9Sstevel@tonic-gate 	    } else {
15247c478bd9Sstevel@tonic-gate 		Wiop[wfd] = wiobuf;
15257c478bd9Sstevel@tonic-gate 		return(NO);			/* bad news */
15267c478bd9Sstevel@tonic-gate 	    }
15277c478bd9Sstevel@tonic-gate 	}
15287c478bd9Sstevel@tonic-gate     }
15297c478bd9Sstevel@tonic-gate     Wiop[wfd] = wiobuf;
15307c478bd9Sstevel@tonic-gate     return(YES);
15317c478bd9Sstevel@tonic-gate }
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate static void
_w_str(char * string)1535*3b296559SToomas Soome _w_str(char *string)
15367c478bd9Sstevel@tonic-gate {
15377c478bd9Sstevel@tonic-gate     int len;
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate     len = strlen(string);
15407c478bd9Sstevel@tonic-gate     if ( write(Cn, string, (unsigned)len) != len )
15417c478bd9Sstevel@tonic-gate 	VERBOSE(gettext(P_LINE_GONE),"");
15427c478bd9Sstevel@tonic-gate     return;
15437c478bd9Sstevel@tonic-gate }
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate static void
_onintrpt(int sig __unused)1546*3b296559SToomas Soome _onintrpt(int sig __unused)
15477c478bd9Sstevel@tonic-gate {
15487c478bd9Sstevel@tonic-gate     (void)signal(SIGINT, _onintrpt);
15497c478bd9Sstevel@tonic-gate     (void)signal(SIGQUIT, _onintrpt);
15507c478bd9Sstevel@tonic-gate     Intrupt = YES;
15517c478bd9Sstevel@tonic-gate     return;
15527c478bd9Sstevel@tonic-gate }
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate static void
_rcvdead(int arg)1555*3b296559SToomas Soome _rcvdead(int arg)	/* this is executed only in the receive process */
15567c478bd9Sstevel@tonic-gate {
15577c478bd9Sstevel@tonic-gate     CDEBUG(4,"call _rcvdead(%d)\r\n", arg);
15587c478bd9Sstevel@tonic-gate     (void)kill(getppid(), SIGUSR1);
15597c478bd9Sstevel@tonic-gate     exit((arg == SIGHUP)? SIGHUP: arg);
15607c478bd9Sstevel@tonic-gate     /*NOTREACHED*/
15617c478bd9Sstevel@tonic-gate }
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate static void
_quit(int arg)1564*3b296559SToomas Soome _quit(int arg)	/* this is executed only in the parent process */
15657c478bd9Sstevel@tonic-gate {
15667c478bd9Sstevel@tonic-gate     CDEBUG(4,"call _quit(%d)\r\n", arg);
15677c478bd9Sstevel@tonic-gate     (void)kill(Child, SIGKILL);
15687c478bd9Sstevel@tonic-gate     _bye(arg);
15697c478bd9Sstevel@tonic-gate     /*NOTREACHED*/
15707c478bd9Sstevel@tonic-gate }
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate static void
_bye(int arg)1573*3b296559SToomas Soome _bye(int arg)	/* this is executed only in the parent proccess */
15747c478bd9Sstevel@tonic-gate {
15757c478bd9Sstevel@tonic-gate     int status;
15767c478bd9Sstevel@tonic-gate     pid_t obit;
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate     if ( Shell > 0 )
15797c478bd9Sstevel@tonic-gate 	while ((obit = wait(&status)) != Shell) {
15807c478bd9Sstevel@tonic-gate 	    if (obit == -1 && errno != EINTR)
15817c478bd9Sstevel@tonic-gate 		break;
15827c478bd9Sstevel@tonic-gate 	    /* _receive (Child) may have ended - check it out */
15837c478bd9Sstevel@tonic-gate 	    if (obit == Child)
15847c478bd9Sstevel@tonic-gate 		Child = 0;
15857c478bd9Sstevel@tonic-gate 	}
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate     /* give user customary message after escape command returns */
15887c478bd9Sstevel@tonic-gate     if (arg == SIGUSR1)
15897c478bd9Sstevel@tonic-gate 	VERBOSE("\r\nLost Carrier\r\n%s", "");
15907c478bd9Sstevel@tonic-gate 
15917c478bd9Sstevel@tonic-gate     CDEBUG(4,"call _bye(%d)\r\n", arg);
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate     (void)signal(SIGINT, SIG_IGN);
15947c478bd9Sstevel@tonic-gate     (void)signal(SIGQUIT, SIG_IGN);
15957c478bd9Sstevel@tonic-gate     /* if _receive() ended already, don't wait for it again */
15967c478bd9Sstevel@tonic-gate     if ( Child != 0 )
15977c478bd9Sstevel@tonic-gate 	while ((obit = wait(&status)) != Child)
15987c478bd9Sstevel@tonic-gate 	    if (obit == -1 && errno != EINTR)
15997c478bd9Sstevel@tonic-gate 		break;
16007c478bd9Sstevel@tonic-gate     VERBOSE("\r\nDisconnected\007\r\n%s", "");
16017c478bd9Sstevel@tonic-gate     cleanup((arg == SIGUSR1)? (status >>= 8): arg);
16027c478bd9Sstevel@tonic-gate     /*NOTREACHED*/
16037c478bd9Sstevel@tonic-gate }
16047c478bd9Sstevel@tonic-gate 
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate void
cleanup(int code)1608*3b296559SToomas Soome cleanup(int code) 	/*this is executed only in the parent process*/
16097c478bd9Sstevel@tonic-gate {
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate     CDEBUG(4,"call cleanup(%d)\r\n", code);
16127c478bd9Sstevel@tonic-gate 
16137c478bd9Sstevel@tonic-gate     if (Docmd) {
16147c478bd9Sstevel@tonic-gate 	if (Child > 0)
16157c478bd9Sstevel@tonic-gate 	    (void)kill(Child, SIGTERM);
16167c478bd9Sstevel@tonic-gate     } else
16177c478bd9Sstevel@tonic-gate 	(void) setuid(Euid);
16187c478bd9Sstevel@tonic-gate     if(Cn > 0) {
16197c478bd9Sstevel@tonic-gate 	fchmod(Cn, Dev_mode);
16207c478bd9Sstevel@tonic-gate 	fd_rmlock(Cn);
16217c478bd9Sstevel@tonic-gate 	(void)close(Cn);
16227c478bd9Sstevel@tonic-gate     }
16237c478bd9Sstevel@tonic-gate 
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate     rmlock((char*) NULL);	/* remove all lock files for this process */
16267c478bd9Sstevel@tonic-gate     if (!Docmd)
16277c478bd9Sstevel@tonic-gate 	_mode(0);
16287c478bd9Sstevel@tonic-gate     exit(code);		/* code=negative for signal causing disconnect*/
16297c478bd9Sstevel@tonic-gate }
16307c478bd9Sstevel@tonic-gate 
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 
16337c478bd9Sstevel@tonic-gate void
tdmp(int arg)1634*3b296559SToomas Soome tdmp(int arg)
16357c478bd9Sstevel@tonic-gate {
16367c478bd9Sstevel@tonic-gate 
16377c478bd9Sstevel@tonic-gate     struct termio xv;
16387c478bd9Sstevel@tonic-gate     int i;
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate     VERBOSE("\rdevice status for fd=%d\r\n", arg);
16417c478bd9Sstevel@tonic-gate     VERBOSE("F_GETFL=%o,", fcntl(arg, F_GETFL,1));
16427c478bd9Sstevel@tonic-gate     if(ioctl(arg, TCGETA, &xv) < 0) {
16437c478bd9Sstevel@tonic-gate 	char	buf[100];
16447c478bd9Sstevel@tonic-gate 	i = errno;
16457c478bd9Sstevel@tonic-gate 	(void)snprintf(buf, sizeof (buf), gettext("\rtdmp for fd=%d"), arg);
16467c478bd9Sstevel@tonic-gate 	errno = i;
16477c478bd9Sstevel@tonic-gate 	perror(buf);
16487c478bd9Sstevel@tonic-gate 	return;
16497c478bd9Sstevel@tonic-gate     }
16507c478bd9Sstevel@tonic-gate     VERBOSE("iflag=`%o',", xv.c_iflag);
16517c478bd9Sstevel@tonic-gate     VERBOSE("oflag=`%o',", xv.c_oflag);
16527c478bd9Sstevel@tonic-gate     VERBOSE("cflag=`%o',", xv.c_cflag);
16537c478bd9Sstevel@tonic-gate     VERBOSE("lflag=`%o',", xv.c_lflag);
16547c478bd9Sstevel@tonic-gate     VERBOSE("line=`%o'\r\n", xv.c_line);
16557c478bd9Sstevel@tonic-gate     VERBOSE("cc[0]=`%o',",  xv.c_cc[0]);
16567c478bd9Sstevel@tonic-gate     for(i=1; i<8; ++i) {
16577c478bd9Sstevel@tonic-gate 	VERBOSE("[%d]=", i);
16587c478bd9Sstevel@tonic-gate 	VERBOSE("`%o',",xv.c_cc[i]);
16597c478bd9Sstevel@tonic-gate     }
16607c478bd9Sstevel@tonic-gate     VERBOSE("\r\n%s", "");
16617c478bd9Sstevel@tonic-gate     return;
16627c478bd9Sstevel@tonic-gate }
16637c478bd9Sstevel@tonic-gate 
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate 
16667c478bd9Sstevel@tonic-gate static void
sysname(char * name)1667*3b296559SToomas Soome sysname(char *name)
16687c478bd9Sstevel@tonic-gate {
16697c478bd9Sstevel@tonic-gate 
1670462be471Sceastha     char *s;
16717c478bd9Sstevel@tonic-gate 
16727c478bd9Sstevel@tonic-gate     if(uname(&utsn) < 0)
16737c478bd9Sstevel@tonic-gate 	s = "Local";
16747c478bd9Sstevel@tonic-gate     else
16757c478bd9Sstevel@tonic-gate 	s = utsn.nodename;
16767c478bd9Sstevel@tonic-gate 
16777c478bd9Sstevel@tonic-gate     strcpy(name, s);
16787c478bd9Sstevel@tonic-gate     return;
16797c478bd9Sstevel@tonic-gate }
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 
16827c478bd9Sstevel@tonic-gate static void
blckcnt(long count)1683*3b296559SToomas Soome blckcnt(long count)
16847c478bd9Sstevel@tonic-gate {
16857c478bd9Sstevel@tonic-gate     static long lcharcnt = 0;
1686462be471Sceastha     long c1, c2;
1687462be471Sceastha     int i;
16887c478bd9Sstevel@tonic-gate     char c;
16897c478bd9Sstevel@tonic-gate 
16907c478bd9Sstevel@tonic-gate     if(count == (long) (-1)) {	/* initialization call */
16917c478bd9Sstevel@tonic-gate 	lcharcnt = 0;
16927c478bd9Sstevel@tonic-gate 	return;
16937c478bd9Sstevel@tonic-gate     }
16947c478bd9Sstevel@tonic-gate     c1 = lcharcnt/BUFSIZ;
16957c478bd9Sstevel@tonic-gate     if(count != (long)(-2)) {	/* regular call */
16967c478bd9Sstevel@tonic-gate 	c2 = count/BUFSIZ;
16977c478bd9Sstevel@tonic-gate 	for(i = c1; i++ < c2;) {
16987c478bd9Sstevel@tonic-gate 	    c = '0' + i%10;
16997c478bd9Sstevel@tonic-gate 	    write(2, &c, 1);
17007c478bd9Sstevel@tonic-gate 	    if(i%NPL == 0)
17017c478bd9Sstevel@tonic-gate 		write(2, "\n\r", 2);
17027c478bd9Sstevel@tonic-gate 	}
17037c478bd9Sstevel@tonic-gate 	lcharcnt = count;
17047c478bd9Sstevel@tonic-gate     } else {
17057c478bd9Sstevel@tonic-gate 	c2 = (lcharcnt + BUFSIZ -1)/BUFSIZ;
17067c478bd9Sstevel@tonic-gate 	if(c1 != c2)
17077c478bd9Sstevel@tonic-gate 	    write(2, "+\n\r", 3);
17087c478bd9Sstevel@tonic-gate 	else if(c2%NPL != 0)
17097c478bd9Sstevel@tonic-gate 	    write(2, "\n\r", 2);
17107c478bd9Sstevel@tonic-gate 	lcharcnt = 0;
17117c478bd9Sstevel@tonic-gate     }
17127c478bd9Sstevel@tonic-gate     return;
17137c478bd9Sstevel@tonic-gate }
17147c478bd9Sstevel@tonic-gate 
17157c478bd9Sstevel@tonic-gate void
assert(char * s1 __unused,char * s2 __unused,int i1 __unused,char * s3 __unused,int i2 __unused)1716*3b296559SToomas Soome assert (char *s1 __unused, char *s2 __unused, int i1 __unused,
1717*3b296559SToomas Soome     char *s3 __unused, int i2 __unused)
1718*3b296559SToomas Soome { 		/* for ASSERT in gnamef.c */
1719*3b296559SToomas Soome }
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate void
logent(char * s1 __unused,char * s2 __unused)1722*3b296559SToomas Soome logent (char *s1 __unused, char *s2 __unused)
1723*3b296559SToomas Soome { 		/* so we can load ulockf() */
1724*3b296559SToomas Soome }
1725