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