1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000, 2001 by Sun Microsystems, Inc. 27*7c478bd9Sstevel@tonic-gate * All rights reserved. 28*7c478bd9Sstevel@tonic-gate */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* from SVR4 cu:cu.c 2.46.2.2 */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * cu [-cdevice] [-sspeed] [-lline] [-bbits] [-h] [-t] [-d] [-n] 35*7c478bd9Sstevel@tonic-gate * [-o|-e] [-L] [-C] telno | systemname [local-cmd] 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * legal baud rates: 300, 1200, 2400, 4800, 9600, 19200, 38400. 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * -c is used to specify which device will be used for making the 40*7c478bd9Sstevel@tonic-gate * call. The device argument is compared to the Type (first) 41*7c478bd9Sstevel@tonic-gate * field in the Devices file, and only those records that 42*7c478bd9Sstevel@tonic-gate * match will be used to make the call. Either -d or -t 43*7c478bd9Sstevel@tonic-gate * would be more intuitive options designations, but they 44*7c478bd9Sstevel@tonic-gate * are already in use. 45*7c478bd9Sstevel@tonic-gate * -l is for specifying a line unit from the file whose 46*7c478bd9Sstevel@tonic-gate * name is defined in /etc/uucp/Devices. 47*7c478bd9Sstevel@tonic-gate * -b is for forcing the number of bits per character processed on 48*7c478bd9Sstevel@tonic-gate * the connection. Valid values are '7' or '8'. 49*7c478bd9Sstevel@tonic-gate * -h is for half-duplex (local echoing). 50*7c478bd9Sstevel@tonic-gate * -t is for adding CR to LF on output to remote (for terminals). 51*7c478bd9Sstevel@tonic-gate * -d can be used to get some tracing & diagnostics. 52*7c478bd9Sstevel@tonic-gate * -o or -e is for odd or even parity on transmission to remote. 53*7c478bd9Sstevel@tonic-gate * -n will request the phone number from the user. 54*7c478bd9Sstevel@tonic-gate * -L will cause cu to go through the login chat sequence in the 55*7c478bd9Sstevel@tonic-gate * Systems file. 56*7c478bd9Sstevel@tonic-gate * -C will cause cu to run the local command specified at the end 57*7c478bd9Sstevel@tonic-gate * of the command line, instead of entering interactive mode. 58*7c478bd9Sstevel@tonic-gate * Telno is a telephone number with `=' for secondary dial-tone. 59*7c478bd9Sstevel@tonic-gate * If "-l dev" is used, speed is taken from /etc/uucp/Devices. 60*7c478bd9Sstevel@tonic-gate * Only systemnames that are included in /etc/uucp/Systems may 61*7c478bd9Sstevel@tonic-gate * be used. 62*7c478bd9Sstevel@tonic-gate * 63*7c478bd9Sstevel@tonic-gate * Escape with `~' at beginning of line: 64*7c478bd9Sstevel@tonic-gate * 65*7c478bd9Sstevel@tonic-gate * ~. quit, 66*7c478bd9Sstevel@tonic-gate * 67*7c478bd9Sstevel@tonic-gate * ~![cmd] execute shell (or 'cmd') locally, 68*7c478bd9Sstevel@tonic-gate * 69*7c478bd9Sstevel@tonic-gate * ~$cmd execute 'cmd' locally, stdout to remote, 70*7c478bd9Sstevel@tonic-gate * 71*7c478bd9Sstevel@tonic-gate * ~%break (alias ~%b) transmit BREAK to remote, 72*7c478bd9Sstevel@tonic-gate * ~%cd [dir] change directory to $HOME (or 'dir'), 73*7c478bd9Sstevel@tonic-gate * ~%debug (alias ~%d) toggles on/off the program debug trace, 74*7c478bd9Sstevel@tonic-gate * ~%divert allow unsolicited diversions to files, 75*7c478bd9Sstevel@tonic-gate * ~%ifc (alias ~%nostop) toggles on/off the DC3/DC1 input control, 76*7c478bd9Sstevel@tonic-gate * ~%ofc (alias ~%noostop) toggles on/off the DC3/DC1 output control, 77*7c478bd9Sstevel@tonic-gate * (certain remote systems cannot cope with DC3 or DC1). 78*7c478bd9Sstevel@tonic-gate * ~%old recognize old style silent diversions, 79*7c478bd9Sstevel@tonic-gate * ~%put from [to] put file from local to remote, 80*7c478bd9Sstevel@tonic-gate * ~%take from [to] take file from remote to local, 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * ~l dump communication line ioctl settings, 83*7c478bd9Sstevel@tonic-gate * ~t dump terminal ioctl settings. 84*7c478bd9Sstevel@tonic-gate * 85*7c478bd9Sstevel@tonic-gate * Silent diversions are enabled only for use with the ~%take 86*7c478bd9Sstevel@tonic-gate * command by default for security reasons. Unsolicited diversions 87*7c478bd9Sstevel@tonic-gate * may be enabled using the ~%divert toggle. The 'new-style' 88*7c478bd9Sstevel@tonic-gate * diversion syntax is "~[local]>:filename", and is terminaled 89*7c478bd9Sstevel@tonic-gate * by "~[local]>", where 'local' is the nodename of the local 90*7c478bd9Sstevel@tonic-gate * system. This enables ~%take to operate properly when cu 91*7c478bd9Sstevel@tonic-gate * is used over multiple hops. 'old-style' diversion syntax may 92*7c478bd9Sstevel@tonic-gate * be enabled using the ~%old toggle. ('old-style' diversion 93*7c478bd9Sstevel@tonic-gate * should be avoided!) 94*7c478bd9Sstevel@tonic-gate * 95*7c478bd9Sstevel@tonic-gate * Cu no longer uses dial.c to reach the remote. Instead, cu places 96*7c478bd9Sstevel@tonic-gate * a telephone call to a remote system through the uucp conn() routine 97*7c478bd9Sstevel@tonic-gate * when the user picks the systemname option or through altconn()-- 98*7c478bd9Sstevel@tonic-gate * which bypasses /etc/uucp/Systems -- if a telno or direct 99*7c478bd9Sstevel@tonic-gate * line is chosen. The line termio attributes are set in fixline(), 100*7c478bd9Sstevel@tonic-gate * before the remote connection is made. As a device-lockout semaphore 101*7c478bd9Sstevel@tonic-gate * mechanism, uucp creates an entry in /var/spool/locks whose name is 102*7c478bd9Sstevel@tonic-gate * LK.<MAJ>.<maj>.<min> where MAJ is the major device of the 103*7c478bd9Sstevel@tonic-gate * filesystem containing the device, and <maj> and <min> are the 104*7c478bd9Sstevel@tonic-gate * major and minor of the device. 105*7c478bd9Sstevel@tonic-gate * When cu terminates, for whatever reason, cleanup() must be 106*7c478bd9Sstevel@tonic-gate * called to "release" the device, and clean up entries from 107*7c478bd9Sstevel@tonic-gate * the locks directory. Cu runs with uucp ownership, and thus provides 108*7c478bd9Sstevel@tonic-gate * extra insurance that lock files will not be left around. 109*7c478bd9Sstevel@tonic-gate */ 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #include "uucp.h" 112*7c478bd9Sstevel@tonic-gate #include <locale.h> 113*7c478bd9Sstevel@tonic-gate #include <stropts.h> 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate #define MID BUFSIZ/2 /* mnemonic */ 116*7c478bd9Sstevel@tonic-gate #define RUB '\177' /* mnemonic */ 117*7c478bd9Sstevel@tonic-gate #define XON '\21' /* mnemonic */ 118*7c478bd9Sstevel@tonic-gate #define XOFF '\23' /* mnemonic */ 119*7c478bd9Sstevel@tonic-gate #define TTYIN 0 /* mnemonic */ 120*7c478bd9Sstevel@tonic-gate #define TTYOUT 1 /* mnemonic */ 121*7c478bd9Sstevel@tonic-gate #define TTYERR 2 /* mnemonic */ 122*7c478bd9Sstevel@tonic-gate #define HUNGUP 2 123*7c478bd9Sstevel@tonic-gate #define YES 1 /* mnemonic */ 124*7c478bd9Sstevel@tonic-gate #define NO 0 /* mnemonic */ 125*7c478bd9Sstevel@tonic-gate #define IOERR 4 /* exit code */ 126*7c478bd9Sstevel@tonic-gate #define MAXPATH 100 127*7c478bd9Sstevel@tonic-gate #define NPL 50 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate int Sflag=0; 130*7c478bd9Sstevel@tonic-gate int Cn; /*fd for remote comm line */ 131*7c478bd9Sstevel@tonic-gate jmp_buf Sjbuf; /*needed by uucp routines*/ 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* io buffering */ 134*7c478bd9Sstevel@tonic-gate /* Wiobuf contains, in effect, 3 write buffers (to remote, to tty */ 135*7c478bd9Sstevel@tonic-gate /* stdout, and to tty stderr) and Riobuf contains 2 read buffers */ 136*7c478bd9Sstevel@tonic-gate /* (from remote, from tty). [WR]IOFD decides which one to use. */ 137*7c478bd9Sstevel@tonic-gate /* [RW]iop holds current position in each. */ 138*7c478bd9Sstevel@tonic-gate #define WIOFD(fd) (fd == TTYOUT ? 0 : (fd == Cn ? 1 : 2)) 139*7c478bd9Sstevel@tonic-gate #define RIOFD(fd) (fd == TTYIN ? 0 : 1) 140*7c478bd9Sstevel@tonic-gate #define WMASK(fd) (fd == Cn ? line_mask : term_mask) 141*7c478bd9Sstevel@tonic-gate #define RMASK(fd) (fd == Cn ? line_mask : term_mask) 142*7c478bd9Sstevel@tonic-gate #define WRIOBSZ 256 143*7c478bd9Sstevel@tonic-gate static char Riobuf[2*WRIOBSZ]; 144*7c478bd9Sstevel@tonic-gate static char Wiobuf[3*WRIOBSZ]; 145*7c478bd9Sstevel@tonic-gate static int Riocnt[2] = {0, 0}; 146*7c478bd9Sstevel@tonic-gate static char *Riop[2]; 147*7c478bd9Sstevel@tonic-gate static char *Wiop[3]; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate extern int optind; /* variable in getopt() */ 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate extern char 152*7c478bd9Sstevel@tonic-gate *optarg; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate static struct call Cucall; /* call structure for altconn() */ 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate static int Saved_tty; /* was TCGETAW of _Tv0 successful? */ 157*7c478bd9Sstevel@tonic-gate static int Saved_termios; /* was TCGETSW of _Tv0 successful? */ 158*7c478bd9Sstevel@tonic-gate static struct termio _Tv, _Tv0; /* for saving, changing TTY atributes */ 159*7c478bd9Sstevel@tonic-gate static struct termios _Tv0s; /* for saving, changing TTY atributes */ 160*7c478bd9Sstevel@tonic-gate static struct termio _Lv; /* attributes for the line to remote */ 161*7c478bd9Sstevel@tonic-gate static struct termios _Lvs; /* attributes for the line to remote */ 162*7c478bd9Sstevel@tonic-gate static char prompt[BUFSIZ]= "["; 163*7c478bd9Sstevel@tonic-gate static struct utsname utsn; 164*7c478bd9Sstevel@tonic-gate static int command_line_hups = 0; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate static char filename[BUFSIZ] = "/dev/null"; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate static char 169*7c478bd9Sstevel@tonic-gate _Cxc, /* place into which we do character io*/ 170*7c478bd9Sstevel@tonic-gate _Tintr, /* current input INTR */ 171*7c478bd9Sstevel@tonic-gate _Tquit, /* current input QUIT */ 172*7c478bd9Sstevel@tonic-gate _Terase, /* current input ERASE */ 173*7c478bd9Sstevel@tonic-gate _Tkill, /* current input KILL */ 174*7c478bd9Sstevel@tonic-gate _Teol, /* current secondary input EOL */ 175*7c478bd9Sstevel@tonic-gate _Myeof, /* current input EOF */ 176*7c478bd9Sstevel@tonic-gate term_mask, /* mask value for local terminal */ 177*7c478bd9Sstevel@tonic-gate line_mask; /* mask value for remote line */ 178*7c478bd9Sstevel@tonic-gate /* either '0177' or '0377' */ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate int 181*7c478bd9Sstevel@tonic-gate Echoe, /* save users ECHOE bit */ 182*7c478bd9Sstevel@tonic-gate Echok, /* save users ECHOK bit */ 183*7c478bd9Sstevel@tonic-gate Intrupt=NO, /* interrupt indicator */ 184*7c478bd9Sstevel@tonic-gate Ifc=YES, /* NO means remote can't XON/XOFF */ 185*7c478bd9Sstevel@tonic-gate Ofc=YES, /* NO means local can't XON/XOFF */ 186*7c478bd9Sstevel@tonic-gate Rtn_code=0, /* default return code */ 187*7c478bd9Sstevel@tonic-gate Divert=NO, /* don't allow unsolicited redirection */ 188*7c478bd9Sstevel@tonic-gate OldStyle=NO, /* don't handle old '~>:filename' syntax */ 189*7c478bd9Sstevel@tonic-gate /* this will be mandatory in SVR4.1 */ 190*7c478bd9Sstevel@tonic-gate Takeflag=NO, /* indicates a ~%take is in progress */ 191*7c478bd9Sstevel@tonic-gate Dologin=NO, /* go through the login chat sequence */ 192*7c478bd9Sstevel@tonic-gate Docmd=NO; /* execute command instead of interactive cu */ 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate EXTERN int /* These are initialized in line.c */ 195*7c478bd9Sstevel@tonic-gate Terminal, /* flag; remote is a terminal */ 196*7c478bd9Sstevel@tonic-gate Oddflag, /* flag- odd parity option*/ 197*7c478bd9Sstevel@tonic-gate Evenflag, /* flag- even parity option*/ 198*7c478bd9Sstevel@tonic-gate Duplex, /* Unix= full duplex=YES; half = NO */ 199*7c478bd9Sstevel@tonic-gate term_8bit, /* is terminal set for 8 bit processing */ 200*7c478bd9Sstevel@tonic-gate line_8bit; /* is line set for 8 bit processing */ 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate EXTERN int clear_hup(); 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate pid_t 205*7c478bd9Sstevel@tonic-gate Child, /* pid for receive process */ 206*7c478bd9Sstevel@tonic-gate Shell; /* pid for escape process */ 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate static pid_t 209*7c478bd9Sstevel@tonic-gate dofork(); /* fork and return pid */ 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate static int 212*7c478bd9Sstevel@tonic-gate r_char(), /* local io routine */ 213*7c478bd9Sstevel@tonic-gate w_char(), /* local io routine */ 214*7c478bd9Sstevel@tonic-gate wioflsh(); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate static void 217*7c478bd9Sstevel@tonic-gate _onintrpt(), /* interrupt routines */ 218*7c478bd9Sstevel@tonic-gate _rcvdead(), 219*7c478bd9Sstevel@tonic-gate _quit(), 220*7c478bd9Sstevel@tonic-gate _bye(); 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate extern void cleanup(); 223*7c478bd9Sstevel@tonic-gate extern void tdmp(); 224*7c478bd9Sstevel@tonic-gate extern int conn(), altconn(), transmit(), tilda(); 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate static void 227*7c478bd9Sstevel@tonic-gate recfork(), 228*7c478bd9Sstevel@tonic-gate sysname(), 229*7c478bd9Sstevel@tonic-gate blckcnt(), 230*7c478bd9Sstevel@tonic-gate _flush(), 231*7c478bd9Sstevel@tonic-gate _shell(), 232*7c478bd9Sstevel@tonic-gate _dopercen(), 233*7c478bd9Sstevel@tonic-gate _receive(), 234*7c478bd9Sstevel@tonic-gate _mode(), 235*7c478bd9Sstevel@tonic-gate _w_str(); 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate extern char *Myline; /* flag to force the requested line to be used */ 238*7c478bd9Sstevel@tonic-gate extern char *Mytype; /* flag to force requested line type to be used 239*7c478bd9Sstevel@tonic-gate * rddev() will compare the string to the D_TYPE 240*7c478bd9Sstevel@tonic-gate * (first) field of the Devices record and skip any 241*7c478bd9Sstevel@tonic-gate * records where they are not equal. Mytype is set 242*7c478bd9Sstevel@tonic-gate * to point to the argument of the -c option from 243*7c478bd9Sstevel@tonic-gate * the command line. */ 244*7c478bd9Sstevel@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"; 245*7c478bd9Sstevel@tonic-gate static char *P_CON_FAILED = "Connect failed: %s\r\n"; 246*7c478bd9Sstevel@tonic-gate static char *P_Ct_OPEN = "Cannot open: %s\r\n"; 247*7c478bd9Sstevel@tonic-gate static char *P_LINE_GONE = "Remote line gone\r\n"; 248*7c478bd9Sstevel@tonic-gate static char *P_Ct_EXSH = "Can't execute shell\r\n"; 249*7c478bd9Sstevel@tonic-gate static char *P_Ct_DIVERT = "Can't divert to %s\r\n"; 250*7c478bd9Sstevel@tonic-gate static char *P_Ct_UNDIVERT = "Can't end diversion to %s\r\n"; 251*7c478bd9Sstevel@tonic-gate static char *P_Bad_DIVERT = "Won't divert to %s. Unsolicited.\r\n"; 252*7c478bd9Sstevel@tonic-gate static char *P_STARTWITH = "Use `~~' to start line with `~'\r\n"; 253*7c478bd9Sstevel@tonic-gate static char *P_CNTAFTER = "File transmission interrupted after %ld bytes.\r\n"; 254*7c478bd9Sstevel@tonic-gate static char *P_CNTLINES = "%d lines/"; 255*7c478bd9Sstevel@tonic-gate static char *P_CNTCHAR = "%ld characters\r\n"; 256*7c478bd9Sstevel@tonic-gate static char *P_FILEINTR = "File transmission interrupted\r\n"; 257*7c478bd9Sstevel@tonic-gate static char *P_Ct_FK = "Can't fork -- try later\r\n"; 258*7c478bd9Sstevel@tonic-gate static char *P_Ct_SPECIAL = "r\nCan't transmit special character `%#o'\r\n"; 259*7c478bd9Sstevel@tonic-gate static char *P_TOOLONG = "\nLine too long\r\n"; 260*7c478bd9Sstevel@tonic-gate static char *P_IOERR = "r\nIO error\r\n"; 261*7c478bd9Sstevel@tonic-gate static char *P_USECMD = "Use `~$'cmd \r\n"; 262*7c478bd9Sstevel@tonic-gate #ifdef forfutureuse 263*7c478bd9Sstevel@tonic-gate static char *P_USEPLUSCMD ="Use `~+'cmd \r\n"; 264*7c478bd9Sstevel@tonic-gate #endif 265*7c478bd9Sstevel@tonic-gate #ifdef u3b 266*7c478bd9Sstevel@tonic-gate static char *P_NOTERMSTAT = "Can't get terminal status\r\n"; 267*7c478bd9Sstevel@tonic-gate static char *P_3BCONSOLE = "Sorry, you can't cu from a 3B console\r\n"; 268*7c478bd9Sstevel@tonic-gate #endif 269*7c478bd9Sstevel@tonic-gate static char *P_TELLENGTH = "Telno cannot exceed 58 digits!\r\n"; 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /*************************************************************** 272*7c478bd9Sstevel@tonic-gate * main: get command line args, establish connection, and fork. 273*7c478bd9Sstevel@tonic-gate * Child invokes "receive" to read from remote & write to TTY. 274*7c478bd9Sstevel@tonic-gate * Main line invokes "transmit" to read TTY & write to remote. 275*7c478bd9Sstevel@tonic-gate ***************************************************************/ 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate main(argc, argv) 278*7c478bd9Sstevel@tonic-gate char *argv[]; 279*7c478bd9Sstevel@tonic-gate { 280*7c478bd9Sstevel@tonic-gate extern void setservice(); 281*7c478bd9Sstevel@tonic-gate extern int sysaccess(); 282*7c478bd9Sstevel@tonic-gate char s[MAXPH]; 283*7c478bd9Sstevel@tonic-gate char *string; 284*7c478bd9Sstevel@tonic-gate int i; 285*7c478bd9Sstevel@tonic-gate int errflag=0; 286*7c478bd9Sstevel@tonic-gate int lflag=0; 287*7c478bd9Sstevel@tonic-gate int nflag=0; 288*7c478bd9Sstevel@tonic-gate int systemname = 0; 289*7c478bd9Sstevel@tonic-gate char vdisable; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /* Set locale environment variables local definitions */ 292*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 293*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 294*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 295*7c478bd9Sstevel@tonic-gate #endif 296*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate Riop[0] = &Riobuf[0]; 299*7c478bd9Sstevel@tonic-gate Riop[1] = &Riobuf[WRIOBSZ]; 300*7c478bd9Sstevel@tonic-gate Wiop[0] = &Wiobuf[0]; 301*7c478bd9Sstevel@tonic-gate Wiop[1] = &Wiobuf[WRIOBSZ]; 302*7c478bd9Sstevel@tonic-gate Wiop[2] = &Wiobuf[2*WRIOBSZ]; 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate Verbose = 1; /*for uucp callers, dialers feedback*/ 305*7c478bd9Sstevel@tonic-gate if ((string = strrchr(argv[0], '/')) != NULL) 306*7c478bd9Sstevel@tonic-gate string++; 307*7c478bd9Sstevel@tonic-gate else 308*7c478bd9Sstevel@tonic-gate string = argv[0]; 309*7c478bd9Sstevel@tonic-gate if (strlcpy(Progname, string, NAMESIZE) >= NAMESIZE) { 310*7c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 311*7c478bd9Sstevel@tonic-gate perror("cu"); 312*7c478bd9Sstevel@tonic-gate exit(1); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate setservice(Progname); 315*7c478bd9Sstevel@tonic-gate if ( sysaccess(EACCESS_SYSTEMS) != 0 ) { 316*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, 317*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot read Systems files\n"), Progname); 318*7c478bd9Sstevel@tonic-gate exit(1); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate if ( sysaccess(EACCESS_DEVICES) != 0 ) { 321*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, 322*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot read Devices files\n"), Progname); 323*7c478bd9Sstevel@tonic-gate exit(1); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate if ( sysaccess(EACCESS_DIALERS) != 0 ) { 326*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, 327*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot read Dialers files\n"), Progname); 328*7c478bd9Sstevel@tonic-gate exit(1); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate Cucall.speed = "Any"; /*default speed*/ 332*7c478bd9Sstevel@tonic-gate Cucall.line = CNULL; 333*7c478bd9Sstevel@tonic-gate Cucall.telno = CNULL; 334*7c478bd9Sstevel@tonic-gate Cucall.type = CNULL; 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate /*Flags for -h, -t, -e, and -o options set here; corresponding line attributes*/ 337*7c478bd9Sstevel@tonic-gate /*are set in fixline() in culine.c before remote connection is made */ 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate while((i = getopt(argc, argv, "dhteons:l:c:b:LCH")) != EOF) 340*7c478bd9Sstevel@tonic-gate switch(i) { 341*7c478bd9Sstevel@tonic-gate case 'd': 342*7c478bd9Sstevel@tonic-gate Debug = 9; /*turns on uucp debugging-level 9*/ 343*7c478bd9Sstevel@tonic-gate break; 344*7c478bd9Sstevel@tonic-gate case 'h': 345*7c478bd9Sstevel@tonic-gate Duplex = NO; 346*7c478bd9Sstevel@tonic-gate Ifc = NO; 347*7c478bd9Sstevel@tonic-gate Ofc = NO; 348*7c478bd9Sstevel@tonic-gate break; 349*7c478bd9Sstevel@tonic-gate case 't': 350*7c478bd9Sstevel@tonic-gate Terminal = YES; 351*7c478bd9Sstevel@tonic-gate break; 352*7c478bd9Sstevel@tonic-gate case 'e': 353*7c478bd9Sstevel@tonic-gate if ( Oddflag ) { 354*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, 355*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot have both even and odd parity\n"), 356*7c478bd9Sstevel@tonic-gate argv[0]); 357*7c478bd9Sstevel@tonic-gate exit(1); 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate Evenflag = 1; 360*7c478bd9Sstevel@tonic-gate break; 361*7c478bd9Sstevel@tonic-gate case 'o': 362*7c478bd9Sstevel@tonic-gate if ( Evenflag ) { 363*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, 364*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot have both even and odd parity\n"), 365*7c478bd9Sstevel@tonic-gate argv[0]); 366*7c478bd9Sstevel@tonic-gate exit(1); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate Oddflag = 1; 369*7c478bd9Sstevel@tonic-gate break; 370*7c478bd9Sstevel@tonic-gate case 'n': 371*7c478bd9Sstevel@tonic-gate nflag++; 372*7c478bd9Sstevel@tonic-gate printf(gettext("Please enter the number: ")); 373*7c478bd9Sstevel@tonic-gate /* Read line from stdin, remove trailing newline, if any */ 374*7c478bd9Sstevel@tonic-gate if (fgets(s, sizeof(s), stdin) != NULL && 375*7c478bd9Sstevel@tonic-gate strchr(s, '\n') != NULL) 376*7c478bd9Sstevel@tonic-gate s[strlen(s)-1] = '\0'; 377*7c478bd9Sstevel@tonic-gate break; 378*7c478bd9Sstevel@tonic-gate case 's': 379*7c478bd9Sstevel@tonic-gate Sflag++; 380*7c478bd9Sstevel@tonic-gate Cucall.speed = optarg; 381*7c478bd9Sstevel@tonic-gate break; 382*7c478bd9Sstevel@tonic-gate case 'l': 383*7c478bd9Sstevel@tonic-gate lflag++; 384*7c478bd9Sstevel@tonic-gate Cucall.line = optarg; 385*7c478bd9Sstevel@tonic-gate break; 386*7c478bd9Sstevel@tonic-gate case 'c': 387*7c478bd9Sstevel@tonic-gate Cucall.type = optarg; 388*7c478bd9Sstevel@tonic-gate Mytype = optarg; 389*7c478bd9Sstevel@tonic-gate break; 390*7c478bd9Sstevel@tonic-gate case 'b': 391*7c478bd9Sstevel@tonic-gate line_8bit = ((*optarg=='7') ? NO : ((*optarg=='8') ? YES : -1)); 392*7c478bd9Sstevel@tonic-gate if ( line_8bit == -1 ) { 393*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 394*7c478bd9Sstevel@tonic-gate gettext("%s: b option value must be '7' or '8'\n"), 395*7c478bd9Sstevel@tonic-gate argv[0]); 396*7c478bd9Sstevel@tonic-gate exit(1); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate break; 399*7c478bd9Sstevel@tonic-gate case 'L': 400*7c478bd9Sstevel@tonic-gate Dologin++; 401*7c478bd9Sstevel@tonic-gate break; 402*7c478bd9Sstevel@tonic-gate case 'C': 403*7c478bd9Sstevel@tonic-gate Docmd++; 404*7c478bd9Sstevel@tonic-gate break; 405*7c478bd9Sstevel@tonic-gate case 'H': 406*7c478bd9Sstevel@tonic-gate command_line_hups++; 407*7c478bd9Sstevel@tonic-gate break; 408*7c478bd9Sstevel@tonic-gate case '?': 409*7c478bd9Sstevel@tonic-gate ++errflag; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate #ifdef u3b 413*7c478bd9Sstevel@tonic-gate { 414*7c478bd9Sstevel@tonic-gate struct stat buff; 415*7c478bd9Sstevel@tonic-gate if(fstat(TTYIN, &buff) < 0) { 416*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_NOTERMSTAT),""); 417*7c478bd9Sstevel@tonic-gate exit(1); 418*7c478bd9Sstevel@tonic-gate } else if ( (buff.st_mode & S_IFMT) == S_IFCHR && buff.st_rdev == 0 ) { 419*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_3BCONSOLE),""); 420*7c478bd9Sstevel@tonic-gate exit(1); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate #endif 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate if((optind < argc && optind > 0) || (nflag && optind > 0)) { 426*7c478bd9Sstevel@tonic-gate if(nflag) 427*7c478bd9Sstevel@tonic-gate string=s; 428*7c478bd9Sstevel@tonic-gate else 429*7c478bd9Sstevel@tonic-gate string = strdup(argv[optind++]); 430*7c478bd9Sstevel@tonic-gate Cucall.telno = string; 431*7c478bd9Sstevel@tonic-gate if ( strlen(string) != strspn(string, "0123456789=-*#") ) { 432*7c478bd9Sstevel@tonic-gate /* if it's not a legitimate telno, then it should be a systemname */ 433*7c478bd9Sstevel@tonic-gate if ( nflag ) { 434*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, gettext("%s: Bad phone number %s\n"), 435*7c478bd9Sstevel@tonic-gate argv[0], string); 436*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Phone numbers may contain " 437*7c478bd9Sstevel@tonic-gate "only the digits 0 through 9 and the special\n" 438*7c478bd9Sstevel@tonic-gate "characters =, -, * and #.\n")); 439*7c478bd9Sstevel@tonic-gate exit(1); 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate systemname++; 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate } else 444*7c478bd9Sstevel@tonic-gate if(Cucall.line == CNULL) /*if none of above, must be direct */ 445*7c478bd9Sstevel@tonic-gate ++errflag; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if(errflag) { 448*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_USAGE), argv[0]); 449*7c478bd9Sstevel@tonic-gate exit(1); 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if ((Cucall.telno != CNULL) && 453*7c478bd9Sstevel@tonic-gate (strlen(Cucall.telno) >= (size_t)(MAXPH - 1))) { 454*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_TELLENGTH),""); 455*7c478bd9Sstevel@tonic-gate exit(0); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* save initial tty state */ 459*7c478bd9Sstevel@tonic-gate if (!(Saved_termios = ( ioctl(TTYIN, TCGETS, &_Tv0s) >= 0 ))) { 460*7c478bd9Sstevel@tonic-gate Saved_tty = ( ioctl(TTYIN, TCGETA, &_Tv0) == 0 ); 461*7c478bd9Sstevel@tonic-gate _Tv0s.c_lflag = _Tv0.c_lflag; 462*7c478bd9Sstevel@tonic-gate _Tv0s.c_oflag = _Tv0.c_oflag; 463*7c478bd9Sstevel@tonic-gate _Tv0s.c_iflag = _Tv0.c_iflag; 464*7c478bd9Sstevel@tonic-gate _Tv0s.c_cflag = _Tv0.c_cflag; 465*7c478bd9Sstevel@tonic-gate for(i = 0; i < NCC; i++) 466*7c478bd9Sstevel@tonic-gate _Tv0s.c_cc[i] = _Tv0.c_cc[i]; 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (Saved_termios || Saved_tty) { 470*7c478bd9Sstevel@tonic-gate char *p; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate /* 473*7c478bd9Sstevel@tonic-gate * We consider the terminal to be in 8 bit mode only if cs8 is set, 474*7c478bd9Sstevel@tonic-gate * istrip is not set, and we're not in the "C" locale. The "C" 475*7c478bd9Sstevel@tonic-gate * locale is by definition 7 bit only. This provides reasonable 476*7c478bd9Sstevel@tonic-gate * compatibility when running in the "C" locale (currently the default) 477*7c478bd9Sstevel@tonic-gate * and connecting to other systems, which are most often 7 bit systems. 478*7c478bd9Sstevel@tonic-gate */ 479*7c478bd9Sstevel@tonic-gate term_8bit = ( (_Tv0s.c_cflag & CS8) && !(_Tv0s.c_iflag & ISTRIP) && 480*7c478bd9Sstevel@tonic-gate ((p = setlocale(LC_CTYPE, NULL)) != NULL) && (strcmp(p, "C") != 0) ); 481*7c478bd9Sstevel@tonic-gate if ( !Oddflag && !Evenflag ) 482*7c478bd9Sstevel@tonic-gate if (_Tv0s.c_cflag & PARENB) 483*7c478bd9Sstevel@tonic-gate if (_Tv0s.c_cflag & PARODD) 484*7c478bd9Sstevel@tonic-gate Oddflag = 1; 485*7c478bd9Sstevel@tonic-gate else 486*7c478bd9Sstevel@tonic-gate Evenflag = 1; 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate if (line_8bit == -1) 490*7c478bd9Sstevel@tonic-gate line_8bit = term_8bit; 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate term_mask = ( term_8bit ? 0377 : 0177 ); 493*7c478bd9Sstevel@tonic-gate line_mask = ( line_8bit ? 0377 : 0177 ); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate /* if not set, use the POSIX disabled designation */ 496*7c478bd9Sstevel@tonic-gate #ifdef _POSIX_VDISABLE 497*7c478bd9Sstevel@tonic-gate vdisable = _POSIX_VDISABLE; 498*7c478bd9Sstevel@tonic-gate #else 499*7c478bd9Sstevel@tonic-gate vdisable = fpathconf(TTYIN, _PC_VDISABLE); 500*7c478bd9Sstevel@tonic-gate #endif 501*7c478bd9Sstevel@tonic-gate _Tintr = _Tv0s.c_cc[VINTR] ? _Tv0s.c_cc[VINTR] : vdisable; 502*7c478bd9Sstevel@tonic-gate _Tquit = _Tv0s.c_cc[VQUIT] ? _Tv0s.c_cc[VQUIT] : vdisable; 503*7c478bd9Sstevel@tonic-gate _Terase = _Tv0s.c_cc[VERASE] ? _Tv0s.c_cc[VERASE] : vdisable; 504*7c478bd9Sstevel@tonic-gate _Tkill = _Tv0s.c_cc[VKILL] ? _Tv0s.c_cc[VKILL] : vdisable; 505*7c478bd9Sstevel@tonic-gate _Teol = _Tv0s.c_cc[VEOL] ? _Tv0s.c_cc[VEOL] : vdisable; 506*7c478bd9Sstevel@tonic-gate _Myeof = _Tv0s.c_cc[VEOF] ? _Tv0s.c_cc[VEOF] : '\04'; 507*7c478bd9Sstevel@tonic-gate Echoe = _Tv0s.c_lflag & ECHOE; 508*7c478bd9Sstevel@tonic-gate Echok = _Tv0s.c_lflag & ECHOK; 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate (void)signal(SIGHUP, cleanup); 511*7c478bd9Sstevel@tonic-gate (void)signal(SIGQUIT, cleanup); 512*7c478bd9Sstevel@tonic-gate (void)signal(SIGINT, cleanup); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate /* place call to system; if "cu systemname", use conn() from uucp 515*7c478bd9Sstevel@tonic-gate directly. Otherwise, use altconn() which dummies in the 516*7c478bd9Sstevel@tonic-gate Systems file line. 517*7c478bd9Sstevel@tonic-gate */ 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate if(systemname) { 520*7c478bd9Sstevel@tonic-gate if ( lflag ) 521*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, 522*7c478bd9Sstevel@tonic-gate gettext("%s: Warning: -l flag ignored when system name used\n"), 523*7c478bd9Sstevel@tonic-gate argv[0]); 524*7c478bd9Sstevel@tonic-gate if ( Sflag ) 525*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, 526*7c478bd9Sstevel@tonic-gate gettext("%s: Warning: -s flag ignored when system name used\n"), 527*7c478bd9Sstevel@tonic-gate argv[0]); 528*7c478bd9Sstevel@tonic-gate Cn = conn(string); 529*7c478bd9Sstevel@tonic-gate if ( (Cn < 0) && (Cucall.type != CNULL) ) 530*7c478bd9Sstevel@tonic-gate Cn = altconn(&Cucall); 531*7c478bd9Sstevel@tonic-gate } else 532*7c478bd9Sstevel@tonic-gate Cn = altconn(&Cucall); 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate if(Cn < 0) { 535*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_CON_FAILED),UERRORTEXT); 536*7c478bd9Sstevel@tonic-gate cleanup(-Cn); 537*7c478bd9Sstevel@tonic-gate } else { 538*7c478bd9Sstevel@tonic-gate struct stat Cnsbuf; 539*7c478bd9Sstevel@tonic-gate if ( fstat(Cn, &Cnsbuf) == 0 ) 540*7c478bd9Sstevel@tonic-gate Dev_mode = Cnsbuf.st_mode; 541*7c478bd9Sstevel@tonic-gate else 542*7c478bd9Sstevel@tonic-gate Dev_mode = R_DEVICEMODE; 543*7c478bd9Sstevel@tonic-gate fchmod(Cn, M_DEVICEMODE); 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate if ((Docmd) && (argv[optind] == NULL)) { 547*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,gettext("cu: local cmd is required, -C is ignored.\n")); 548*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_USAGE), argv[0]); 549*7c478bd9Sstevel@tonic-gate Docmd=NO; 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate if (!Docmd) { 553*7c478bd9Sstevel@tonic-gate Euid = geteuid(); 554*7c478bd9Sstevel@tonic-gate if((setuid(getuid()) < 0) || (setgid(getgid()) < 0)) { 555*7c478bd9Sstevel@tonic-gate VERBOSE("Unable to setuid/gid\n%s", ""); 556*7c478bd9Sstevel@tonic-gate cleanup(101); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate if(Debug) 561*7c478bd9Sstevel@tonic-gate tdmp(Cn); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate /* At this point succeeded in getting an open communication line */ 564*7c478bd9Sstevel@tonic-gate /* Conn() takes care of closing the Systems file */ 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate if (!Docmd) { 567*7c478bd9Sstevel@tonic-gate (void)signal(SIGINT,_onintrpt); 568*7c478bd9Sstevel@tonic-gate _mode(1); /* put terminal in `raw' mode */ 569*7c478bd9Sstevel@tonic-gate VERBOSE("Connected\007\r\n%s", ""); /*bell!*/ 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate /* must catch signals before fork. if not and if _receive() */ 572*7c478bd9Sstevel@tonic-gate /* fails in just the right (wrong?) way, _rcvdead() can be */ 573*7c478bd9Sstevel@tonic-gate /* called and do "kill(getppid(),SIGUSR1);" before parent */ 574*7c478bd9Sstevel@tonic-gate /* has done calls to signal() after recfork(). */ 575*7c478bd9Sstevel@tonic-gate (void)signal(SIGUSR1, _bye); 576*7c478bd9Sstevel@tonic-gate (void)signal(SIGHUP, cleanup); 577*7c478bd9Sstevel@tonic-gate (void)signal(SIGQUIT, _onintrpt); 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate sysname(&prompt[1]); /* set up system name prompt */ 580*7c478bd9Sstevel@tonic-gate (void) strcat(prompt, "]"); 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate recfork(); /* checks for child == 0 */ 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate if(Child > 0) { 585*7c478bd9Sstevel@tonic-gate /* 586*7c478bd9Sstevel@tonic-gate * Because the child counts hangups for the -H flag, 587*7c478bd9Sstevel@tonic-gate * and because we fork a new child when doing (e.g.) 588*7c478bd9Sstevel@tonic-gate * ~%take, we assume the first child we fork has 589*7c478bd9Sstevel@tonic-gate * processed all the hangups and we reset the count here. 590*7c478bd9Sstevel@tonic-gate * We really should pass the remaining count back from 591*7c478bd9Sstevel@tonic-gate * the child to the parent when we kill the child. 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate command_line_hups = 0; 594*7c478bd9Sstevel@tonic-gate Rtn_code = transmit(); 595*7c478bd9Sstevel@tonic-gate _quit(Rtn_code); 596*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate } else { 599*7c478bd9Sstevel@tonic-gate /* 600*7c478bd9Sstevel@tonic-gate * Fork a child to run the specified command, 601*7c478bd9Sstevel@tonic-gate * wait for it to finish, and clean up. 602*7c478bd9Sstevel@tonic-gate */ 603*7c478bd9Sstevel@tonic-gate Child = dofork(); 604*7c478bd9Sstevel@tonic-gate if (Child == 0) { 605*7c478bd9Sstevel@tonic-gate close(0); 606*7c478bd9Sstevel@tonic-gate close(1); 607*7c478bd9Sstevel@tonic-gate dup(Cn); 608*7c478bd9Sstevel@tonic-gate dup(Cn); 609*7c478bd9Sstevel@tonic-gate close(Cn); 610*7c478bd9Sstevel@tonic-gate setgid(getgid()); 611*7c478bd9Sstevel@tonic-gate setuid(getuid()); 612*7c478bd9Sstevel@tonic-gate execvp(argv[optind], &argv[optind]); 613*7c478bd9Sstevel@tonic-gate exit(-1); 614*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate wait(0); 617*7c478bd9Sstevel@tonic-gate /* XXX - should return wait status as our exit code */ 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate cleanup(Cn); 620*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate /* 624*7c478bd9Sstevel@tonic-gate * Kill the present child, if it exists, then fork a new one. 625*7c478bd9Sstevel@tonic-gate */ 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate static void 628*7c478bd9Sstevel@tonic-gate recfork() 629*7c478bd9Sstevel@tonic-gate { 630*7c478bd9Sstevel@tonic-gate int ret, status; 631*7c478bd9Sstevel@tonic-gate if (Child) { 632*7c478bd9Sstevel@tonic-gate kill(Child, SIGKILL); 633*7c478bd9Sstevel@tonic-gate while ( (ret = wait(&status)) != Child ) 634*7c478bd9Sstevel@tonic-gate if (ret == -1 && errno != EINTR) 635*7c478bd9Sstevel@tonic-gate break; 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate Child = dofork(); 638*7c478bd9Sstevel@tonic-gate if(Child == 0) { 639*7c478bd9Sstevel@tonic-gate (void)signal(SIGUSR1, SIG_DFL); 640*7c478bd9Sstevel@tonic-gate (void)signal(SIGHUP, _rcvdead); 641*7c478bd9Sstevel@tonic-gate (void)signal(SIGQUIT, SIG_IGN); 642*7c478bd9Sstevel@tonic-gate (void)signal(SIGINT, SIG_IGN); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate _receive(); /* This should run until killed */ 645*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate return; 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /*************************************************************** 651*7c478bd9Sstevel@tonic-gate * transmit: copy stdin to remote fd, except: 652*7c478bd9Sstevel@tonic-gate * ~. terminate 653*7c478bd9Sstevel@tonic-gate * ~! local login-style shell 654*7c478bd9Sstevel@tonic-gate * ~!cmd execute cmd locally 655*7c478bd9Sstevel@tonic-gate * ~$proc execute proc locally, send output to line 656*7c478bd9Sstevel@tonic-gate * ~%cmd execute builtin cmd (put, take, or break) 657*7c478bd9Sstevel@tonic-gate ****************************************************************/ 658*7c478bd9Sstevel@tonic-gate #ifdef forfutureuse 659*7c478bd9Sstevel@tonic-gate /***************************************************************** 660*7c478bd9Sstevel@tonic-gate * ~+proc execute locally, with stdout to and stdin from line. 661*7c478bd9Sstevel@tonic-gate ******************************************************************/ 662*7c478bd9Sstevel@tonic-gate #endif 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate int 665*7c478bd9Sstevel@tonic-gate transmit() 666*7c478bd9Sstevel@tonic-gate { 667*7c478bd9Sstevel@tonic-gate char b[BUFSIZ]; 668*7c478bd9Sstevel@tonic-gate register char *p; 669*7c478bd9Sstevel@tonic-gate register int escape; 670*7c478bd9Sstevel@tonic-gate register int id = 0; /*flag for systemname prompt on tilda escape*/ 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate CDEBUG(4,"transmit started\n\r%s", ""); 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate /* In main loop, always waiting to read characters from */ 675*7c478bd9Sstevel@tonic-gate /* keyboard; writes characters to remote, or to TTYOUT */ 676*7c478bd9Sstevel@tonic-gate /* on a tilda escape */ 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate for (;;) { 679*7c478bd9Sstevel@tonic-gate p = b; 680*7c478bd9Sstevel@tonic-gate while(r_char(TTYIN) == YES) { 681*7c478bd9Sstevel@tonic-gate if(p == b) /* Escape on leading ~ */ 682*7c478bd9Sstevel@tonic-gate escape = (_Cxc == '~'); 683*7c478bd9Sstevel@tonic-gate if(p == b+1) /* But not on leading ~~ */ 684*7c478bd9Sstevel@tonic-gate escape &= (_Cxc != '~'); 685*7c478bd9Sstevel@tonic-gate if(escape) { 686*7c478bd9Sstevel@tonic-gate if(_Cxc == '\n' || _Cxc == '\r' || _Cxc == _Teol) { 687*7c478bd9Sstevel@tonic-gate *p = '\0'; 688*7c478bd9Sstevel@tonic-gate if(tilda(b+1) == YES) 689*7c478bd9Sstevel@tonic-gate return(0); 690*7c478bd9Sstevel@tonic-gate id = 0; 691*7c478bd9Sstevel@tonic-gate break; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate if(_Cxc == _Tintr || _Cxc == _Tkill || _Cxc == _Tquit || 694*7c478bd9Sstevel@tonic-gate (Intrupt && _Cxc == '\0')) { 695*7c478bd9Sstevel@tonic-gate if(_Cxc == _Tkill) { 696*7c478bd9Sstevel@tonic-gate if(Echok) 697*7c478bd9Sstevel@tonic-gate VERBOSE("\r\n%s", ""); 698*7c478bd9Sstevel@tonic-gate } else { 699*7c478bd9Sstevel@tonic-gate _Cxc = '\r'; 700*7c478bd9Sstevel@tonic-gate if( w_char(Cn) == NO) { 701*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_LINE_GONE),""); 702*7c478bd9Sstevel@tonic-gate return(IOERR); 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate id=0; 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate break; 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate if((p == b+1) && (_Cxc != _Terase) && (!id)) { 709*7c478bd9Sstevel@tonic-gate id = 1; 710*7c478bd9Sstevel@tonic-gate VERBOSE("%s", prompt); 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate if(_Cxc == _Terase) { 713*7c478bd9Sstevel@tonic-gate p = (--p < b)? b:p; 714*7c478bd9Sstevel@tonic-gate if(p > b) 715*7c478bd9Sstevel@tonic-gate if(Echoe) { 716*7c478bd9Sstevel@tonic-gate VERBOSE("\b \b%s", ""); 717*7c478bd9Sstevel@tonic-gate } else 718*7c478bd9Sstevel@tonic-gate (void)w_char(TTYOUT); 719*7c478bd9Sstevel@tonic-gate } else { 720*7c478bd9Sstevel@tonic-gate (void)w_char(TTYOUT); 721*7c478bd9Sstevel@tonic-gate if(p-b < BUFSIZ) 722*7c478bd9Sstevel@tonic-gate *p++ = _Cxc; 723*7c478bd9Sstevel@tonic-gate else { 724*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_TOOLONG),""); 725*7c478bd9Sstevel@tonic-gate break; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate } 728*7c478bd9Sstevel@tonic-gate /*not a tilda escape command*/ 729*7c478bd9Sstevel@tonic-gate } else { 730*7c478bd9Sstevel@tonic-gate if(Intrupt && _Cxc == '\0') { 731*7c478bd9Sstevel@tonic-gate CDEBUG(4,"got break in transmit\n\r%s", ""); 732*7c478bd9Sstevel@tonic-gate Intrupt = NO; 733*7c478bd9Sstevel@tonic-gate (*genbrk)(Cn); 734*7c478bd9Sstevel@tonic-gate _flush(); 735*7c478bd9Sstevel@tonic-gate break; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate if(w_char(Cn) == NO) { 738*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_LINE_GONE),""); 739*7c478bd9Sstevel@tonic-gate return(IOERR); 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate if(Duplex == NO) { 742*7c478bd9Sstevel@tonic-gate if((w_char(TTYERR) == NO) || (wioflsh(TTYERR) == NO)) 743*7c478bd9Sstevel@tonic-gate return(IOERR); 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate if ((_Cxc == _Tintr) || (_Cxc == _Tquit) || 746*7c478bd9Sstevel@tonic-gate ( (p==b) && (_Cxc == _Myeof) ) ) { 747*7c478bd9Sstevel@tonic-gate CDEBUG(4,"got a tintr\n\r%s", ""); 748*7c478bd9Sstevel@tonic-gate _flush(); 749*7c478bd9Sstevel@tonic-gate break; 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate if(_Cxc == '\n' || _Cxc == '\r' || 752*7c478bd9Sstevel@tonic-gate _Cxc == _Teol || _Cxc == _Tkill) { 753*7c478bd9Sstevel@tonic-gate id=0; 754*7c478bd9Sstevel@tonic-gate Takeflag = NO; 755*7c478bd9Sstevel@tonic-gate break; 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate p = (char*)0; 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate /*************************************************************** 764*7c478bd9Sstevel@tonic-gate * routine to halt input from remote and flush buffers 765*7c478bd9Sstevel@tonic-gate ***************************************************************/ 766*7c478bd9Sstevel@tonic-gate static void 767*7c478bd9Sstevel@tonic-gate _flush() 768*7c478bd9Sstevel@tonic-gate { 769*7c478bd9Sstevel@tonic-gate (void)ioctl(TTYOUT, TCXONC, 0); /* stop tty output */ 770*7c478bd9Sstevel@tonic-gate (void)ioctl(Cn, TCFLSH, 0); /* flush remote input */ 771*7c478bd9Sstevel@tonic-gate (void)ioctl(TTYOUT, TCFLSH, 1); /* flush tty output */ 772*7c478bd9Sstevel@tonic-gate (void)ioctl(TTYOUT, TCXONC, 1); /* restart tty output */ 773*7c478bd9Sstevel@tonic-gate if(Takeflag == NO) { 774*7c478bd9Sstevel@tonic-gate return; /* didn't interupt file transmission */ 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_FILEINTR),""); 777*7c478bd9Sstevel@tonic-gate (void)sleep(3); 778*7c478bd9Sstevel@tonic-gate _w_str("echo '\n~>\n';mesg y;stty echo\n"); 779*7c478bd9Sstevel@tonic-gate Takeflag = NO; 780*7c478bd9Sstevel@tonic-gate return; 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate /************************************************************** 784*7c478bd9Sstevel@tonic-gate * command interpreter for escape lines 785*7c478bd9Sstevel@tonic-gate **************************************************************/ 786*7c478bd9Sstevel@tonic-gate int 787*7c478bd9Sstevel@tonic-gate tilda(cmd) 788*7c478bd9Sstevel@tonic-gate register char *cmd; 789*7c478bd9Sstevel@tonic-gate { 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate VERBOSE("\r\n%s", ""); 792*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call tilda(%s)\r\n", cmd); 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate switch(cmd[0]) { 795*7c478bd9Sstevel@tonic-gate case CSUSP: 796*7c478bd9Sstevel@tonic-gate case CDSUSP: 797*7c478bd9Sstevel@tonic-gate _mode(0); 798*7c478bd9Sstevel@tonic-gate kill(cmd[0] == CDSUSP ? getpid() : (pid_t) 0, SIGTSTP); 799*7c478bd9Sstevel@tonic-gate _mode(1); 800*7c478bd9Sstevel@tonic-gate break; 801*7c478bd9Sstevel@tonic-gate case '.': 802*7c478bd9Sstevel@tonic-gate if(Cucall.telno == CNULL) 803*7c478bd9Sstevel@tonic-gate if(cmd[1] != '.') { 804*7c478bd9Sstevel@tonic-gate _w_str("\04\04\04\04\04"); 805*7c478bd9Sstevel@tonic-gate if (Child) 806*7c478bd9Sstevel@tonic-gate kill(Child, SIGKILL); 807*7c478bd9Sstevel@tonic-gate if (ioctl (Cn, TCGETS, &_Lvs) < 0) { 808*7c478bd9Sstevel@tonic-gate (void) ioctl (Cn, TCGETA, &_Lv); 809*7c478bd9Sstevel@tonic-gate /* speed to zero for hangup */ 810*7c478bd9Sstevel@tonic-gate _Lv.c_cflag = 0; 811*7c478bd9Sstevel@tonic-gate (void) ioctl (Cn, TCSETAW, &_Lv); 812*7c478bd9Sstevel@tonic-gate } else { 813*7c478bd9Sstevel@tonic-gate /* speed to zero for hangup */ 814*7c478bd9Sstevel@tonic-gate _Lvs.c_cflag &= 0xffff0000; 815*7c478bd9Sstevel@tonic-gate cfsetospeed(&_Lvs, B0); 816*7c478bd9Sstevel@tonic-gate (void) ioctl (Cn, TCSETSW, &_Lvs); 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate (void) sleep (2); 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate return(YES); 821*7c478bd9Sstevel@tonic-gate case '!': 822*7c478bd9Sstevel@tonic-gate _shell(cmd); /* local shell */ 823*7c478bd9Sstevel@tonic-gate VERBOSE("\r%c\r\n", *cmd); 824*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 825*7c478bd9Sstevel@tonic-gate break; 826*7c478bd9Sstevel@tonic-gate case '$': 827*7c478bd9Sstevel@tonic-gate if(cmd[1] == '\0') { 828*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_USECMD),""); 829*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 830*7c478bd9Sstevel@tonic-gate } else { 831*7c478bd9Sstevel@tonic-gate _shell(cmd); /*Local shell */ 832*7c478bd9Sstevel@tonic-gate VERBOSE("\r%c\r\n", *cmd); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate break; 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate #ifdef forfutureuse 837*7c478bd9Sstevel@tonic-gate case '+': 838*7c478bd9Sstevel@tonic-gate if(cmd[1] == '\0') { 839*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_USEPLUSCMD), ""); 840*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 841*7c478bd9Sstevel@tonic-gate } else { 842*7c478bd9Sstevel@tonic-gate if (*cmd == '+') 843*7c478bd9Sstevel@tonic-gate /* must suspend receive to give*/ 844*7c478bd9Sstevel@tonic-gate /*remote out to stdin of cmd */ 845*7c478bd9Sstevel@tonic-gate kill(Child, SIGKILL); 846*7c478bd9Sstevel@tonic-gate _shell(cmd); /* Local shell */ 847*7c478bd9Sstevel@tonic-gate if (*cmd == '+') 848*7c478bd9Sstevel@tonic-gate recfork(); 849*7c478bd9Sstevel@tonic-gate VERBOSE("\r%c\r\n", *cmd); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate break; 852*7c478bd9Sstevel@tonic-gate #endif 853*7c478bd9Sstevel@tonic-gate case '%': 854*7c478bd9Sstevel@tonic-gate _dopercen(++cmd); 855*7c478bd9Sstevel@tonic-gate break; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate case 't': 858*7c478bd9Sstevel@tonic-gate tdmp(TTYIN); 859*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 860*7c478bd9Sstevel@tonic-gate break; 861*7c478bd9Sstevel@tonic-gate case 'l': 862*7c478bd9Sstevel@tonic-gate tdmp(Cn); 863*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 864*7c478bd9Sstevel@tonic-gate break; 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate default: 867*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_STARTWITH),""); 868*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 869*7c478bd9Sstevel@tonic-gate break; 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate return(NO); 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate /*************************************************************** 875*7c478bd9Sstevel@tonic-gate * The routine "shell" takes an argument starting with 876*7c478bd9Sstevel@tonic-gate * either "!" or "$", and terminated with '\0'. 877*7c478bd9Sstevel@tonic-gate * If $arg, arg is the name of a local shell file which 878*7c478bd9Sstevel@tonic-gate * is executed and its output is passed to the remote. 879*7c478bd9Sstevel@tonic-gate * If !arg, we escape to a local shell to execute arg 880*7c478bd9Sstevel@tonic-gate * with output to TTY, and if arg is null, escape to 881*7c478bd9Sstevel@tonic-gate * a local shell and blind the remote line. In either 882*7c478bd9Sstevel@tonic-gate * case, '^D' will kill the escape status. 883*7c478bd9Sstevel@tonic-gate **************************************************************/ 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate #ifdef forfutureuse 886*7c478bd9Sstevel@tonic-gate /*************************************************************** 887*7c478bd9Sstevel@tonic-gate * Another argument to the routine "shell" may be +. If +arg, 888*7c478bd9Sstevel@tonic-gate * arg is the name of a local shell file which is executed with 889*7c478bd9Sstevel@tonic-gate * stdin from and stdout to the remote. 890*7c478bd9Sstevel@tonic-gate **************************************************************/ 891*7c478bd9Sstevel@tonic-gate #endif 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate static void 894*7c478bd9Sstevel@tonic-gate _shell(str) 895*7c478bd9Sstevel@tonic-gate char *str; 896*7c478bd9Sstevel@tonic-gate { 897*7c478bd9Sstevel@tonic-gate pid_t fk, w_ret; 898*7c478bd9Sstevel@tonic-gate void (*xx)(), (*yy)(); 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call _shell(%s)\r\n", str); 901*7c478bd9Sstevel@tonic-gate fk = dofork(); 902*7c478bd9Sstevel@tonic-gate if(fk < 0) 903*7c478bd9Sstevel@tonic-gate return; 904*7c478bd9Sstevel@tonic-gate Shell = fk; 905*7c478bd9Sstevel@tonic-gate _mode(0); /* restore normal tty attributes */ 906*7c478bd9Sstevel@tonic-gate xx = signal(SIGINT, SIG_IGN); 907*7c478bd9Sstevel@tonic-gate yy = signal(SIGQUIT, SIG_IGN); 908*7c478bd9Sstevel@tonic-gate if(fk == 0) { 909*7c478bd9Sstevel@tonic-gate char *shell; 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate if( (shell = getenv("SHELL")) == NULL) 912*7c478bd9Sstevel@tonic-gate /* use default if user's shell is not set */ 913*7c478bd9Sstevel@tonic-gate shell = SHELL; 914*7c478bd9Sstevel@tonic-gate (void)close(TTYOUT); 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate /*********************************************** 917*7c478bd9Sstevel@tonic-gate * Hook-up our "standard output" 918*7c478bd9Sstevel@tonic-gate * to either the tty for '!' or the line 919*7c478bd9Sstevel@tonic-gate * for '$' as appropriate 920*7c478bd9Sstevel@tonic-gate ***********************************************/ 921*7c478bd9Sstevel@tonic-gate #ifdef forfutureuse 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate /************************************************ 924*7c478bd9Sstevel@tonic-gate * Or to the line for '+'. 925*7c478bd9Sstevel@tonic-gate **********************************************/ 926*7c478bd9Sstevel@tonic-gate #endif 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate (void)fcntl((*str == '!')? TTYERR:Cn,F_DUPFD,TTYOUT); 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate #ifdef forfutureuse 931*7c478bd9Sstevel@tonic-gate /************************************************* 932*7c478bd9Sstevel@tonic-gate * Hook-up "standard input" to the line for '+'. 933*7c478bd9Sstevel@tonic-gate * **********************************************/ 934*7c478bd9Sstevel@tonic-gate if (*str == '+') { 935*7c478bd9Sstevel@tonic-gate (void)close(TTYIN); 936*7c478bd9Sstevel@tonic-gate (void)fcntl(Cn,F_DUPFD,TTYIN); 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate #endif 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate /*********************************************** 941*7c478bd9Sstevel@tonic-gate * Hook-up our "standard input" 942*7c478bd9Sstevel@tonic-gate * to the tty for '!' and '$'. 943*7c478bd9Sstevel@tonic-gate ***********************************************/ 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate (void)close(Cn); /*parent still has Cn*/ 946*7c478bd9Sstevel@tonic-gate (void)signal(SIGINT, SIG_DFL); 947*7c478bd9Sstevel@tonic-gate (void)signal(SIGHUP, SIG_DFL); 948*7c478bd9Sstevel@tonic-gate (void)signal(SIGQUIT, SIG_DFL); 949*7c478bd9Sstevel@tonic-gate (void)signal(SIGUSR1, SIG_DFL); 950*7c478bd9Sstevel@tonic-gate if(*++str == '\0') 951*7c478bd9Sstevel@tonic-gate (void)execl(shell,shell,(char*) 0,(char*) 0,(char *) 0); 952*7c478bd9Sstevel@tonic-gate else 953*7c478bd9Sstevel@tonic-gate (void)execl(shell,"sh","-c",str,(char *) 0); 954*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_Ct_EXSH),""); 955*7c478bd9Sstevel@tonic-gate exit(0); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate while ((w_ret = wait((int*)0)) != fk) 958*7c478bd9Sstevel@tonic-gate if (w_ret == -1 && errno != EINTR) 959*7c478bd9Sstevel@tonic-gate break; 960*7c478bd9Sstevel@tonic-gate Shell = 0; 961*7c478bd9Sstevel@tonic-gate (void)signal(SIGINT, xx); 962*7c478bd9Sstevel@tonic-gate (void)signal(SIGQUIT, yy); 963*7c478bd9Sstevel@tonic-gate _mode(1); 964*7c478bd9Sstevel@tonic-gate return; 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate /*************************************************************** 969*7c478bd9Sstevel@tonic-gate * This function implements the 'put', 'take', 'break', 970*7c478bd9Sstevel@tonic-gate * 'ifc' (aliased to nostop) and 'ofc' (aliased to noostop) 971*7c478bd9Sstevel@tonic-gate * commands which are internal to cu. 972*7c478bd9Sstevel@tonic-gate ***************************************************************/ 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate static void 975*7c478bd9Sstevel@tonic-gate _dopercen(cmd) 976*7c478bd9Sstevel@tonic-gate register char *cmd; 977*7c478bd9Sstevel@tonic-gate { 978*7c478bd9Sstevel@tonic-gate char *arg[5]; 979*7c478bd9Sstevel@tonic-gate char *getpath; 980*7c478bd9Sstevel@tonic-gate char mypath[MAXPATH]; 981*7c478bd9Sstevel@tonic-gate int narg; 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate blckcnt((long)(-1)); 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call _dopercen(\"%s\")\r\n", cmd); 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate arg[narg=0] = strtok(cmd, " \t\n"); 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate /* following loop breaks out the command and args */ 990*7c478bd9Sstevel@tonic-gate while((arg[++narg] = strtok((char*) NULL, " \t\n")) != NULL) { 991*7c478bd9Sstevel@tonic-gate if(narg < 4) 992*7c478bd9Sstevel@tonic-gate continue; 993*7c478bd9Sstevel@tonic-gate else 994*7c478bd9Sstevel@tonic-gate break; 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate /* ~%take file option */ 998*7c478bd9Sstevel@tonic-gate if(EQUALS(arg[0], "take")) { 999*7c478bd9Sstevel@tonic-gate if(narg < 2 || narg > 3) { 1000*7c478bd9Sstevel@tonic-gate VERBOSE("usage: ~%%take from [to]\r\n%s", ""); 1001*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1002*7c478bd9Sstevel@tonic-gate return; 1003*7c478bd9Sstevel@tonic-gate } 1004*7c478bd9Sstevel@tonic-gate if(narg == 2) 1005*7c478bd9Sstevel@tonic-gate arg[2] = arg[1]; 1006*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, arg[2]); 1007*7c478bd9Sstevel@tonic-gate recfork(); /* fork so child (receive) knows filename */ 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate /* 1010*7c478bd9Sstevel@tonic-gate * be sure that the remote file (arg[1]) exists before 1011*7c478bd9Sstevel@tonic-gate * you try to take it. otherwise, the error message from 1012*7c478bd9Sstevel@tonic-gate * cat will wind up in the local file (arg[2]) 1013*7c478bd9Sstevel@tonic-gate * 1014*7c478bd9Sstevel@tonic-gate * what we're doing is: 1015*7c478bd9Sstevel@tonic-gate * stty -echo; \ 1016*7c478bd9Sstevel@tonic-gate * if test -r arg1 1017*7c478bd9Sstevel@tonic-gate * then (echo '~[local]'>arg2; cat arg1; echo '~[local]'>) 1018*7c478bd9Sstevel@tonic-gate * else echo can't open: arg1 1019*7c478bd9Sstevel@tonic-gate * fi; \ 1020*7c478bd9Sstevel@tonic-gate * stty echo 1021*7c478bd9Sstevel@tonic-gate * 1022*7c478bd9Sstevel@tonic-gate */ 1023*7c478bd9Sstevel@tonic-gate _w_str("stty -echo;if test -r "); 1024*7c478bd9Sstevel@tonic-gate _w_str(arg[1]); 1025*7c478bd9Sstevel@tonic-gate _w_str("; then (echo '~"); 1026*7c478bd9Sstevel@tonic-gate _w_str(prompt); 1027*7c478bd9Sstevel@tonic-gate _w_str(">'"); 1028*7c478bd9Sstevel@tonic-gate _w_str(arg[2]); 1029*7c478bd9Sstevel@tonic-gate _w_str(";cat "); 1030*7c478bd9Sstevel@tonic-gate _w_str(arg[1]); 1031*7c478bd9Sstevel@tonic-gate _w_str(";echo '~"); 1032*7c478bd9Sstevel@tonic-gate _w_str(prompt); 1033*7c478bd9Sstevel@tonic-gate _w_str(">'); else echo cant\\'t open: "); 1034*7c478bd9Sstevel@tonic-gate _w_str(arg[1]); 1035*7c478bd9Sstevel@tonic-gate _w_str("; fi;stty echo\n"); 1036*7c478bd9Sstevel@tonic-gate Takeflag = YES; 1037*7c478bd9Sstevel@tonic-gate return; 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate /* ~%put file option*/ 1040*7c478bd9Sstevel@tonic-gate if(EQUALS(arg[0], "put")) { 1041*7c478bd9Sstevel@tonic-gate FILE *file; 1042*7c478bd9Sstevel@tonic-gate char ch, buf[BUFSIZ], spec[NCC+1], *b, *p, *q; 1043*7c478bd9Sstevel@tonic-gate int i, j, len, tc=0, lines=0; 1044*7c478bd9Sstevel@tonic-gate long chars=0L; 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate if(narg < 2 || narg > 3) { 1047*7c478bd9Sstevel@tonic-gate VERBOSE("usage: ~%%put from [to]\r\n%s", ""); 1048*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1049*7c478bd9Sstevel@tonic-gate return; 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate if(narg == 2) 1052*7c478bd9Sstevel@tonic-gate arg[2] = arg[1]; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate if((file = fopen(arg[1], "r")) == NULL) { 1055*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_Ct_OPEN), arg[1]); 1056*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1057*7c478bd9Sstevel@tonic-gate return; 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate /* 1060*7c478bd9Sstevel@tonic-gate * if cannot write into file on remote machine, write into 1061*7c478bd9Sstevel@tonic-gate * /dev/null 1062*7c478bd9Sstevel@tonic-gate * 1063*7c478bd9Sstevel@tonic-gate * what we're doing is: 1064*7c478bd9Sstevel@tonic-gate * stty -echo 1065*7c478bd9Sstevel@tonic-gate * (cat - > arg2) || cat - > /dev/null 1066*7c478bd9Sstevel@tonic-gate * stty echo 1067*7c478bd9Sstevel@tonic-gate */ 1068*7c478bd9Sstevel@tonic-gate _w_str("stty -echo;(cat - >"); 1069*7c478bd9Sstevel@tonic-gate _w_str(arg[2]); 1070*7c478bd9Sstevel@tonic-gate _w_str(")||cat - >/dev/null;stty echo\n"); 1071*7c478bd9Sstevel@tonic-gate Intrupt = NO; 1072*7c478bd9Sstevel@tonic-gate for(i=0,j=0; i < NCC; ++i) 1073*7c478bd9Sstevel@tonic-gate if((ch=_Tv0s.c_cc[i]) != '\0') 1074*7c478bd9Sstevel@tonic-gate spec[j++] = ch; 1075*7c478bd9Sstevel@tonic-gate spec[j] = '\0'; 1076*7c478bd9Sstevel@tonic-gate _mode(2); /*accept interrupts from keyboard*/ 1077*7c478bd9Sstevel@tonic-gate (void)sleep(5); /*hope that w_str info digested*/ 1078*7c478bd9Sstevel@tonic-gate 1079*7c478bd9Sstevel@tonic-gate /* Read characters line by line into buf to write to */ 1080*7c478bd9Sstevel@tonic-gate /* remote with character and line count for blckcnt */ 1081*7c478bd9Sstevel@tonic-gate while(Intrupt == NO && 1082*7c478bd9Sstevel@tonic-gate fgets(b= &buf[MID],MID,file) != NULL) { 1083*7c478bd9Sstevel@tonic-gate /* worse case is each char must be escaped*/ 1084*7c478bd9Sstevel@tonic-gate len = strlen(b); 1085*7c478bd9Sstevel@tonic-gate chars += len; /* character count */ 1086*7c478bd9Sstevel@tonic-gate p = b; 1087*7c478bd9Sstevel@tonic-gate while(q = strpbrk(p, spec)) { 1088*7c478bd9Sstevel@tonic-gate if(*q == _Tintr || *q == _Tquit || *q == _Teol) { 1089*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_Ct_SPECIAL), *q); 1090*7c478bd9Sstevel@tonic-gate (void)strcpy(q, q+1); 1091*7c478bd9Sstevel@tonic-gate Intrupt = YES; 1092*7c478bd9Sstevel@tonic-gate } else { 1093*7c478bd9Sstevel@tonic-gate b = strncpy(b-1, b, q-b); 1094*7c478bd9Sstevel@tonic-gate *(q-1) = '\\'; 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate p = q+1; 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate if((tc += len) >= MID) { 1099*7c478bd9Sstevel@tonic-gate (void)sleep(1); 1100*7c478bd9Sstevel@tonic-gate tc = len; 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate if(write(Cn, b, (unsigned)strlen(b)) < 0) { 1103*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_IOERR),""); 1104*7c478bd9Sstevel@tonic-gate Intrupt = YES; 1105*7c478bd9Sstevel@tonic-gate break; 1106*7c478bd9Sstevel@tonic-gate } 1107*7c478bd9Sstevel@tonic-gate ++lines; /* line count */ 1108*7c478bd9Sstevel@tonic-gate blckcnt((long)chars); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate _mode(1); 1111*7c478bd9Sstevel@tonic-gate blckcnt((long)(-2)); /* close */ 1112*7c478bd9Sstevel@tonic-gate (void)fclose(file); 1113*7c478bd9Sstevel@tonic-gate if(Intrupt == YES) { 1114*7c478bd9Sstevel@tonic-gate Intrupt = NO; 1115*7c478bd9Sstevel@tonic-gate _w_str("\n"); 1116*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_CNTAFTER), ++chars); 1117*7c478bd9Sstevel@tonic-gate } else { 1118*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_CNTLINES), lines); 1119*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_CNTCHAR),chars); 1120*7c478bd9Sstevel@tonic-gate } 1121*7c478bd9Sstevel@tonic-gate (void)sleep(3); 1122*7c478bd9Sstevel@tonic-gate _w_str("\04"); 1123*7c478bd9Sstevel@tonic-gate return; 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate /* ~%b or ~%break */ 1127*7c478bd9Sstevel@tonic-gate if(EQUALS(arg[0], "b") || EQUALS(arg[0], "break")) { 1128*7c478bd9Sstevel@tonic-gate (*genbrk)(Cn); 1129*7c478bd9Sstevel@tonic-gate return; 1130*7c478bd9Sstevel@tonic-gate } 1131*7c478bd9Sstevel@tonic-gate /* ~%d or ~%debug toggle */ 1132*7c478bd9Sstevel@tonic-gate if(EQUALS(arg[0], "d") || EQUALS(arg[0], "debug")) { 1133*7c478bd9Sstevel@tonic-gate if(Debug == 0) 1134*7c478bd9Sstevel@tonic-gate Debug = 9; 1135*7c478bd9Sstevel@tonic-gate else 1136*7c478bd9Sstevel@tonic-gate Debug = 0; 1137*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1138*7c478bd9Sstevel@tonic-gate return; 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate /* ~%[ifc|nostop] toggles start/stop input control */ 1141*7c478bd9Sstevel@tonic-gate if( EQUALS(arg[0], "ifc") || EQUALS(arg[0], "nostop") ) { 1142*7c478bd9Sstevel@tonic-gate (void)ioctl(Cn, TCGETA, &_Tv); 1143*7c478bd9Sstevel@tonic-gate Ifc = !Ifc; 1144*7c478bd9Sstevel@tonic-gate if(Ifc == YES) 1145*7c478bd9Sstevel@tonic-gate _Tv.c_iflag |= IXOFF; 1146*7c478bd9Sstevel@tonic-gate else 1147*7c478bd9Sstevel@tonic-gate _Tv.c_iflag &= ~IXOFF; 1148*7c478bd9Sstevel@tonic-gate (void)ioctl(Cn, TCSETAW, &_Tv); 1149*7c478bd9Sstevel@tonic-gate _mode(1); 1150*7c478bd9Sstevel@tonic-gate VERBOSE("(ifc %s)", (Ifc ? "enabled" : "disabled")); 1151*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1152*7c478bd9Sstevel@tonic-gate return; 1153*7c478bd9Sstevel@tonic-gate } 1154*7c478bd9Sstevel@tonic-gate /* ~%[ofc|noostop] toggles start/stop output control */ 1155*7c478bd9Sstevel@tonic-gate if( EQUALS(arg[0], "ofc") || EQUALS(arg[0], "noostop") ) { 1156*7c478bd9Sstevel@tonic-gate (void)ioctl(Cn, TCGETA, &_Tv); 1157*7c478bd9Sstevel@tonic-gate Ofc = !Ofc; 1158*7c478bd9Sstevel@tonic-gate if(Ofc == YES) 1159*7c478bd9Sstevel@tonic-gate _Tv.c_iflag |= IXON; 1160*7c478bd9Sstevel@tonic-gate else 1161*7c478bd9Sstevel@tonic-gate _Tv.c_iflag &= ~IXON; 1162*7c478bd9Sstevel@tonic-gate (void)ioctl(Cn, TCSETAW, &_Tv); 1163*7c478bd9Sstevel@tonic-gate _mode(1); 1164*7c478bd9Sstevel@tonic-gate VERBOSE("(ofc %s)", (Ofc ? "enabled" : "disabled")); 1165*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1166*7c478bd9Sstevel@tonic-gate return; 1167*7c478bd9Sstevel@tonic-gate } 1168*7c478bd9Sstevel@tonic-gate /* ~%divert toggles unsolicited redirection security */ 1169*7c478bd9Sstevel@tonic-gate if( EQUALS(arg[0], "divert") ) { 1170*7c478bd9Sstevel@tonic-gate Divert = !Divert; 1171*7c478bd9Sstevel@tonic-gate recfork(); /* fork a new child so it knows about change */ 1172*7c478bd9Sstevel@tonic-gate VERBOSE("(unsolicited diversion %s)", (Divert ? "enabled" : "disabled")); 1173*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1174*7c478bd9Sstevel@tonic-gate return; 1175*7c478bd9Sstevel@tonic-gate } 1176*7c478bd9Sstevel@tonic-gate /* ~%old toggles recognition of old-style '~>:filename' */ 1177*7c478bd9Sstevel@tonic-gate if( EQUALS(arg[0], "old") ) { 1178*7c478bd9Sstevel@tonic-gate OldStyle = !OldStyle; 1179*7c478bd9Sstevel@tonic-gate recfork(); /* fork a new child so it knows about change */ 1180*7c478bd9Sstevel@tonic-gate VERBOSE("(old-style diversion %s)", (OldStyle ? "enabled" : "disabled")); 1181*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1182*7c478bd9Sstevel@tonic-gate return; 1183*7c478bd9Sstevel@tonic-gate } 1184*7c478bd9Sstevel@tonic-gate /* Change local current directory */ 1185*7c478bd9Sstevel@tonic-gate if(EQUALS(arg[0], "cd")) { 1186*7c478bd9Sstevel@tonic-gate if (narg < 2) { 1187*7c478bd9Sstevel@tonic-gate getpath = getenv("HOME"); 1188*7c478bd9Sstevel@tonic-gate strlcpy(mypath, getpath, sizeof (mypath)); 1189*7c478bd9Sstevel@tonic-gate if(chdir(mypath) < 0) { 1190*7c478bd9Sstevel@tonic-gate VERBOSE("Cannot change to %s\r\n", mypath); 1191*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1192*7c478bd9Sstevel@tonic-gate return; 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate } else if (chdir(arg[1]) < 0) { 1195*7c478bd9Sstevel@tonic-gate VERBOSE("Cannot change to %s\r\n", arg[1]); 1196*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1197*7c478bd9Sstevel@tonic-gate return; 1198*7c478bd9Sstevel@tonic-gate } 1199*7c478bd9Sstevel@tonic-gate recfork(); /* fork a new child so it knows about change */ 1200*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1201*7c478bd9Sstevel@tonic-gate return; 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate if (arg[0] == (char *) NULL) 1205*7c478bd9Sstevel@tonic-gate arg[0] = ""; 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate VERBOSE("~%%%s unknown to cu\r\n", arg[0]); 1208*7c478bd9Sstevel@tonic-gate VERBOSE("(continue)%s", ""); 1209*7c478bd9Sstevel@tonic-gate return; 1210*7c478bd9Sstevel@tonic-gate } 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate /*************************************************************** 1213*7c478bd9Sstevel@tonic-gate * receive: read from remote line, write to fd=1 (TTYOUT) 1214*7c478bd9Sstevel@tonic-gate * catch: 1215*7c478bd9Sstevel@tonic-gate * ~>[>]:file 1216*7c478bd9Sstevel@tonic-gate * . 1217*7c478bd9Sstevel@tonic-gate * . stuff for file 1218*7c478bd9Sstevel@tonic-gate * . 1219*7c478bd9Sstevel@tonic-gate * ~> (ends diversion) 1220*7c478bd9Sstevel@tonic-gate ***************************************************************/ 1221*7c478bd9Sstevel@tonic-gate 1222*7c478bd9Sstevel@tonic-gate static void 1223*7c478bd9Sstevel@tonic-gate _receive() 1224*7c478bd9Sstevel@tonic-gate { 1225*7c478bd9Sstevel@tonic-gate register silent = NO, file = -1; 1226*7c478bd9Sstevel@tonic-gate register char *p; 1227*7c478bd9Sstevel@tonic-gate int tic; 1228*7c478bd9Sstevel@tonic-gate int for_me = NO; 1229*7c478bd9Sstevel@tonic-gate char b[BUFSIZ]; 1230*7c478bd9Sstevel@tonic-gate char *b_p; 1231*7c478bd9Sstevel@tonic-gate long count; 1232*7c478bd9Sstevel@tonic-gate int line_ok = 1, rval; 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate CDEBUG(4,"_receive started\r\n%s", ""); 1235*7c478bd9Sstevel@tonic-gate 1236*7c478bd9Sstevel@tonic-gate b[0] = '\0'; 1237*7c478bd9Sstevel@tonic-gate b_p = p = b; 1238*7c478bd9Sstevel@tonic-gate 1239*7c478bd9Sstevel@tonic-gate while(line_ok) { 1240*7c478bd9Sstevel@tonic-gate rval = r_char(Cn); 1241*7c478bd9Sstevel@tonic-gate if (rval == NO) { 1242*7c478bd9Sstevel@tonic-gate line_ok = 0; 1243*7c478bd9Sstevel@tonic-gate continue; 1244*7c478bd9Sstevel@tonic-gate } 1245*7c478bd9Sstevel@tonic-gate if (rval == HUNGUP) { 1246*7c478bd9Sstevel@tonic-gate if (command_line_hups > 0) { 1247*7c478bd9Sstevel@tonic-gate CDEBUG(4, "Ignoring device hangup\n%s", ""); 1248*7c478bd9Sstevel@tonic-gate command_line_hups--; 1249*7c478bd9Sstevel@tonic-gate (void) setuid(Euid); /* reacquire privileges */ 1250*7c478bd9Sstevel@tonic-gate if (clear_hup(Cn) != SUCCESS) { 1251*7c478bd9Sstevel@tonic-gate DEBUG(4, "Unable to clear hup on device\n%s", ""); 1252*7c478bd9Sstevel@tonic-gate line_ok = 0; 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate (void) setuid(getuid()); /* relinquish privileges */ 1255*7c478bd9Sstevel@tonic-gate } else 1256*7c478bd9Sstevel@tonic-gate line_ok = 0; 1257*7c478bd9Sstevel@tonic-gate continue; 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate if(silent == NO) /* ie., if not redirecting from screen */ 1261*7c478bd9Sstevel@tonic-gate if(w_char(TTYOUT) == NO) 1262*7c478bd9Sstevel@tonic-gate _rcvdead(IOERR); /* this will exit */ 1263*7c478bd9Sstevel@tonic-gate /* remove CR's and fill inserted by remote */ 1264*7c478bd9Sstevel@tonic-gate if(_Cxc == '\0' || _Cxc == RUB || _Cxc == '\r') 1265*7c478bd9Sstevel@tonic-gate continue; 1266*7c478bd9Sstevel@tonic-gate *p++ = _Cxc; 1267*7c478bd9Sstevel@tonic-gate if(_Cxc != '\n' && (p-b) < BUFSIZ) 1268*7c478bd9Sstevel@tonic-gate continue; 1269*7c478bd9Sstevel@tonic-gate /* ****************************************** */ 1270*7c478bd9Sstevel@tonic-gate /* This code deals with ~%take file diversion */ 1271*7c478bd9Sstevel@tonic-gate /* ****************************************** */ 1272*7c478bd9Sstevel@tonic-gate if (b[0] == '~') { 1273*7c478bd9Sstevel@tonic-gate int append; 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate if (EQUALSN(&b[1],prompt,strlen(prompt))) { 1276*7c478bd9Sstevel@tonic-gate b_p = b + 1 + strlen(prompt); 1277*7c478bd9Sstevel@tonic-gate for_me = YES; 1278*7c478bd9Sstevel@tonic-gate } else { 1279*7c478bd9Sstevel@tonic-gate b_p = b + 1; 1280*7c478bd9Sstevel@tonic-gate for_me = NO; 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate if ( (for_me || OldStyle) && (*b_p == '>') ) { 1283*7c478bd9Sstevel@tonic-gate /* This is an acceptable '~[uname]>' line */ 1284*7c478bd9Sstevel@tonic-gate b_p++; 1285*7c478bd9Sstevel@tonic-gate if ( (*b_p == '\n') && (silent == YES) ) { 1286*7c478bd9Sstevel@tonic-gate /* end of diversion */ 1287*7c478bd9Sstevel@tonic-gate *b_p = '\0'; 1288*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, "/dev/null"); 1289*7c478bd9Sstevel@tonic-gate if ( file >= 0 && close(file) ) { 1290*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_Ct_UNDIVERT), b_p); 1291*7c478bd9Sstevel@tonic-gate perror(gettext("cu: close failed")); 1292*7c478bd9Sstevel@tonic-gate VERBOSE("%s","\r"); 1293*7c478bd9Sstevel@tonic-gate } 1294*7c478bd9Sstevel@tonic-gate silent = NO; 1295*7c478bd9Sstevel@tonic-gate blckcnt((long)(-2)); 1296*7c478bd9Sstevel@tonic-gate VERBOSE("%s\r\n", b); 1297*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_CNTLINES), tic); 1298*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_CNTCHAR), count); 1299*7c478bd9Sstevel@tonic-gate file = -1; 1300*7c478bd9Sstevel@tonic-gate p = b; 1301*7c478bd9Sstevel@tonic-gate continue; 1302*7c478bd9Sstevel@tonic-gate } else if (*b_p != '\n') { 1303*7c478bd9Sstevel@tonic-gate if ( *b_p == '>' ) { 1304*7c478bd9Sstevel@tonic-gate append = 1; 1305*7c478bd9Sstevel@tonic-gate b_p++; 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate if ( (for_me || (OldStyle && (*b_p == ':'))) && (silent == NO) ) { 1308*7c478bd9Sstevel@tonic-gate /* terminate filename string */ 1309*7c478bd9Sstevel@tonic-gate *(p-1) = '\0'; 1310*7c478bd9Sstevel@tonic-gate if ( *b_p == ':' ) 1311*7c478bd9Sstevel@tonic-gate b_p++; 1312*7c478bd9Sstevel@tonic-gate if ( !EQUALS(filename, b_p) ) { 1313*7c478bd9Sstevel@tonic-gate if ( !Divert || !EQUALS(filename, "/dev/null") ) { 1314*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_Bad_DIVERT), b_p); 1315*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, "/dev/null"); 1316*7c478bd9Sstevel@tonic-gate append = 1; 1317*7c478bd9Sstevel@tonic-gate } else { 1318*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, b_p); 1319*7c478bd9Sstevel@tonic-gate } 1320*7c478bd9Sstevel@tonic-gate } 1321*7c478bd9Sstevel@tonic-gate if ( append && ((file=open(filename,O_WRONLY)) >= 0) ) 1322*7c478bd9Sstevel@tonic-gate (void)lseek(file, 0L, 2); 1323*7c478bd9Sstevel@tonic-gate else 1324*7c478bd9Sstevel@tonic-gate file = creat(filename, PUB_FILEMODE); 1325*7c478bd9Sstevel@tonic-gate if (file < 0) { 1326*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_Ct_DIVERT), filename); 1327*7c478bd9Sstevel@tonic-gate perror(gettext("cu: open|creat failed")); 1328*7c478bd9Sstevel@tonic-gate VERBOSE("%s","\r"); 1329*7c478bd9Sstevel@tonic-gate (void)sleep(5); /* 10 seemed too long*/ 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate silent = YES; 1332*7c478bd9Sstevel@tonic-gate count = tic = 0; 1333*7c478bd9Sstevel@tonic-gate p = b; 1334*7c478bd9Sstevel@tonic-gate continue; 1335*7c478bd9Sstevel@tonic-gate } 1336*7c478bd9Sstevel@tonic-gate } 1337*7c478bd9Sstevel@tonic-gate } 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate /* Regular data, divert if appropriate */ 1340*7c478bd9Sstevel@tonic-gate if ( silent == YES ) { 1341*7c478bd9Sstevel@tonic-gate if ( file >= 0) 1342*7c478bd9Sstevel@tonic-gate (void)write(file, b, (unsigned)(p-b)); 1343*7c478bd9Sstevel@tonic-gate count += p-b; /* tally char count */ 1344*7c478bd9Sstevel@tonic-gate ++tic; /* tally lines */ 1345*7c478bd9Sstevel@tonic-gate blckcnt((long)count); 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate p = b; 1348*7c478bd9Sstevel@tonic-gate } 1349*7c478bd9Sstevel@tonic-gate /* 1350*7c478bd9Sstevel@tonic-gate * we used to tell of lost carrier here, but now 1351*7c478bd9Sstevel@tonic-gate * defer to _bye() so that escape processes are 1352*7c478bd9Sstevel@tonic-gate * not interrupted. 1353*7c478bd9Sstevel@tonic-gate */ 1354*7c478bd9Sstevel@tonic-gate _rcvdead(IOERR); 1355*7c478bd9Sstevel@tonic-gate return; 1356*7c478bd9Sstevel@tonic-gate } 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate /*************************************************************** 1359*7c478bd9Sstevel@tonic-gate * change the TTY attributes of the users terminal: 1360*7c478bd9Sstevel@tonic-gate * 0 means restore attributes to pre-cu status. 1361*7c478bd9Sstevel@tonic-gate * 1 means set `raw' mode for use during cu session. 1362*7c478bd9Sstevel@tonic-gate * 2 means like 1 but accept interrupts from the keyboard. 1363*7c478bd9Sstevel@tonic-gate ***************************************************************/ 1364*7c478bd9Sstevel@tonic-gate static void 1365*7c478bd9Sstevel@tonic-gate _mode(arg) 1366*7c478bd9Sstevel@tonic-gate { 1367*7c478bd9Sstevel@tonic-gate int i; 1368*7c478bd9Sstevel@tonic-gate 1369*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call _mode(%d)\r\n", arg); 1370*7c478bd9Sstevel@tonic-gate if(arg == 0) { 1371*7c478bd9Sstevel@tonic-gate if ( Saved_termios ) 1372*7c478bd9Sstevel@tonic-gate (void)ioctl(TTYIN, TCSETSW, &_Tv0s); 1373*7c478bd9Sstevel@tonic-gate else if ( Saved_tty ) { 1374*7c478bd9Sstevel@tonic-gate _Tv0.c_lflag = _Tv0s.c_lflag; 1375*7c478bd9Sstevel@tonic-gate _Tv0.c_oflag = _Tv0s.c_oflag; 1376*7c478bd9Sstevel@tonic-gate _Tv0.c_iflag = _Tv0s.c_iflag; 1377*7c478bd9Sstevel@tonic-gate _Tv0.c_cflag = _Tv0s.c_cflag; 1378*7c478bd9Sstevel@tonic-gate for(i = 0; i < NCC; i++) 1379*7c478bd9Sstevel@tonic-gate _Tv0.c_cc[i] = _Tv0s.c_cc[i]; 1380*7c478bd9Sstevel@tonic-gate (void)ioctl(TTYIN, TCSETAW, &_Tv0); 1381*7c478bd9Sstevel@tonic-gate } 1382*7c478bd9Sstevel@tonic-gate } else { 1383*7c478bd9Sstevel@tonic-gate (void)ioctl(TTYIN, TCGETA, &_Tv); 1384*7c478bd9Sstevel@tonic-gate if(arg == 1) { 1385*7c478bd9Sstevel@tonic-gate _Tv.c_iflag &= ~(INLCR | ICRNL | IGNCR | IUCLC); 1386*7c478bd9Sstevel@tonic-gate if ( !term_8bit ) 1387*7c478bd9Sstevel@tonic-gate _Tv.c_iflag |= ISTRIP; 1388*7c478bd9Sstevel@tonic-gate _Tv.c_oflag |= OPOST; 1389*7c478bd9Sstevel@tonic-gate _Tv.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET); 1390*7c478bd9Sstevel@tonic-gate _Tv.c_lflag &= ~(ICANON | ISIG | ECHO); 1391*7c478bd9Sstevel@tonic-gate if(Ifc == NO) 1392*7c478bd9Sstevel@tonic-gate _Tv.c_iflag &= ~IXON; 1393*7c478bd9Sstevel@tonic-gate else 1394*7c478bd9Sstevel@tonic-gate _Tv.c_iflag |= IXON; 1395*7c478bd9Sstevel@tonic-gate if(Ofc == NO) 1396*7c478bd9Sstevel@tonic-gate _Tv.c_iflag &= ~IXOFF; 1397*7c478bd9Sstevel@tonic-gate else 1398*7c478bd9Sstevel@tonic-gate _Tv.c_iflag |= IXOFF; 1399*7c478bd9Sstevel@tonic-gate if(Terminal) { 1400*7c478bd9Sstevel@tonic-gate _Tv.c_oflag |= ONLCR; 1401*7c478bd9Sstevel@tonic-gate _Tv.c_iflag |= ICRNL; 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate _Tv.c_cc[VEOF] = '\01'; 1404*7c478bd9Sstevel@tonic-gate _Tv.c_cc[VEOL] = '\0'; 1405*7c478bd9Sstevel@tonic-gate } 1406*7c478bd9Sstevel@tonic-gate if(arg == 2) { 1407*7c478bd9Sstevel@tonic-gate _Tv.c_iflag |= IXON; 1408*7c478bd9Sstevel@tonic-gate _Tv.c_lflag |= ISIG; 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate (void)ioctl(TTYIN, TCSETAW, &_Tv); 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate return; 1413*7c478bd9Sstevel@tonic-gate } 1414*7c478bd9Sstevel@tonic-gate 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate static pid_t 1417*7c478bd9Sstevel@tonic-gate dofork() 1418*7c478bd9Sstevel@tonic-gate { 1419*7c478bd9Sstevel@tonic-gate register int i; 1420*7c478bd9Sstevel@tonic-gate pid_t x; 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate for(i = 0; i < 6; ++i) { 1423*7c478bd9Sstevel@tonic-gate if((x = fork()) >= 0) { 1424*7c478bd9Sstevel@tonic-gate return(x); 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate } 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate if(Debug) perror("dofork"); 1429*7c478bd9Sstevel@tonic-gate 1430*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_Ct_FK),""); 1431*7c478bd9Sstevel@tonic-gate return(x); 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate static int 1435*7c478bd9Sstevel@tonic-gate r_char(fd) 1436*7c478bd9Sstevel@tonic-gate { 1437*7c478bd9Sstevel@tonic-gate int rtn = 1, rfd; 1438*7c478bd9Sstevel@tonic-gate char *riobuf; 1439*7c478bd9Sstevel@tonic-gate 1440*7c478bd9Sstevel@tonic-gate /* find starting pos in correct buffer in Riobuf */ 1441*7c478bd9Sstevel@tonic-gate rfd = RIOFD(fd); 1442*7c478bd9Sstevel@tonic-gate riobuf = &Riobuf[rfd*WRIOBSZ]; 1443*7c478bd9Sstevel@tonic-gate 1444*7c478bd9Sstevel@tonic-gate if (Riop[rfd] >= &riobuf[Riocnt[rfd]]) { 1445*7c478bd9Sstevel@tonic-gate /* empty read buffer - refill it */ 1446*7c478bd9Sstevel@tonic-gate 1447*7c478bd9Sstevel@tonic-gate /* flush any waiting output */ 1448*7c478bd9Sstevel@tonic-gate if ( (wioflsh(Cn) == NO ) || (wioflsh(TTYOUT) == NO) ) 1449*7c478bd9Sstevel@tonic-gate return(NO); 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate while((rtn = read(fd, riobuf, WRIOBSZ)) < 0){ 1452*7c478bd9Sstevel@tonic-gate if(errno == EINTR) { 1453*7c478bd9Sstevel@tonic-gate /* onintrpt() called asynchronously before this line */ 1454*7c478bd9Sstevel@tonic-gate if(Intrupt == YES) { 1455*7c478bd9Sstevel@tonic-gate /* got a BREAK */ 1456*7c478bd9Sstevel@tonic-gate _Cxc = '\0'; 1457*7c478bd9Sstevel@tonic-gate return(YES); 1458*7c478bd9Sstevel@tonic-gate } else { 1459*7c478bd9Sstevel@tonic-gate /*a signal other than interrupt*/ 1460*7c478bd9Sstevel@tonic-gate /*received during read*/ 1461*7c478bd9Sstevel@tonic-gate continue; 1462*7c478bd9Sstevel@tonic-gate } 1463*7c478bd9Sstevel@tonic-gate } else { 1464*7c478bd9Sstevel@tonic-gate CDEBUG(4,"got read error, not EINTR\n\r%s", ""); 1465*7c478bd9Sstevel@tonic-gate break; /* something wrong */ 1466*7c478bd9Sstevel@tonic-gate } 1467*7c478bd9Sstevel@tonic-gate } 1468*7c478bd9Sstevel@tonic-gate if (rtn > 0) { 1469*7c478bd9Sstevel@tonic-gate /* reset current position in buffer */ 1470*7c478bd9Sstevel@tonic-gate /* and count of available chars */ 1471*7c478bd9Sstevel@tonic-gate Riop[rfd] = riobuf; 1472*7c478bd9Sstevel@tonic-gate Riocnt[rfd] = rtn; 1473*7c478bd9Sstevel@tonic-gate } 1474*7c478bd9Sstevel@tonic-gate } 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate if ( rtn > 0 ) { 1477*7c478bd9Sstevel@tonic-gate _Cxc = *(Riop[rfd]++) & RMASK(fd); /* mask off appropriate bits */ 1478*7c478bd9Sstevel@tonic-gate return(YES); 1479*7c478bd9Sstevel@tonic-gate } else if (rtn == 0) { 1480*7c478bd9Sstevel@tonic-gate _Cxc = '\0'; 1481*7c478bd9Sstevel@tonic-gate return (HUNGUP); 1482*7c478bd9Sstevel@tonic-gate } else { 1483*7c478bd9Sstevel@tonic-gate _Cxc = '\0'; 1484*7c478bd9Sstevel@tonic-gate return(NO); 1485*7c478bd9Sstevel@tonic-gate } 1486*7c478bd9Sstevel@tonic-gate } 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate static int 1489*7c478bd9Sstevel@tonic-gate w_char(fd) 1490*7c478bd9Sstevel@tonic-gate { 1491*7c478bd9Sstevel@tonic-gate int wfd; 1492*7c478bd9Sstevel@tonic-gate char *wiobuf; 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate /* find starting pos in correct buffer in Wiobuf */ 1495*7c478bd9Sstevel@tonic-gate wfd = WIOFD(fd); 1496*7c478bd9Sstevel@tonic-gate wiobuf = &Wiobuf[wfd*WRIOBSZ]; 1497*7c478bd9Sstevel@tonic-gate 1498*7c478bd9Sstevel@tonic-gate if (Wiop[wfd] >= &wiobuf[WRIOBSZ]) { 1499*7c478bd9Sstevel@tonic-gate /* full output buffer - flush it */ 1500*7c478bd9Sstevel@tonic-gate if ( wioflsh(fd) == NO ) 1501*7c478bd9Sstevel@tonic-gate return(NO); 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate *(Wiop[wfd]++) = _Cxc & WMASK(fd); /* mask off appropriate bits */ 1504*7c478bd9Sstevel@tonic-gate return(YES); 1505*7c478bd9Sstevel@tonic-gate } 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate /* wioflsh flush output buffer */ 1508*7c478bd9Sstevel@tonic-gate static int 1509*7c478bd9Sstevel@tonic-gate wioflsh(fd) 1510*7c478bd9Sstevel@tonic-gate int fd; 1511*7c478bd9Sstevel@tonic-gate { 1512*7c478bd9Sstevel@tonic-gate int wfd; 1513*7c478bd9Sstevel@tonic-gate char *wiobuf; 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate /* find starting pos in correct buffer in Wiobuf */ 1516*7c478bd9Sstevel@tonic-gate wfd = WIOFD(fd); 1517*7c478bd9Sstevel@tonic-gate wiobuf = &Wiobuf[wfd*WRIOBSZ]; 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate if (Wiop[wfd] > wiobuf) { 1520*7c478bd9Sstevel@tonic-gate /* there's something in the buffer */ 1521*7c478bd9Sstevel@tonic-gate while(write(fd, wiobuf, (Wiop[wfd] - wiobuf)) < 0) { 1522*7c478bd9Sstevel@tonic-gate if(errno == EINTR) { 1523*7c478bd9Sstevel@tonic-gate if(Intrupt == YES) { 1524*7c478bd9Sstevel@tonic-gate VERBOSE("\ncu: Output blocked\r\n%s", ""); 1525*7c478bd9Sstevel@tonic-gate _quit(IOERR); 1526*7c478bd9Sstevel@tonic-gate } else 1527*7c478bd9Sstevel@tonic-gate continue; /* alarm went off */ 1528*7c478bd9Sstevel@tonic-gate } else { 1529*7c478bd9Sstevel@tonic-gate Wiop[wfd] = wiobuf; 1530*7c478bd9Sstevel@tonic-gate return(NO); /* bad news */ 1531*7c478bd9Sstevel@tonic-gate } 1532*7c478bd9Sstevel@tonic-gate } 1533*7c478bd9Sstevel@tonic-gate } 1534*7c478bd9Sstevel@tonic-gate Wiop[wfd] = wiobuf; 1535*7c478bd9Sstevel@tonic-gate return(YES); 1536*7c478bd9Sstevel@tonic-gate } 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate 1539*7c478bd9Sstevel@tonic-gate static void 1540*7c478bd9Sstevel@tonic-gate _w_str(string) 1541*7c478bd9Sstevel@tonic-gate register char *string; 1542*7c478bd9Sstevel@tonic-gate { 1543*7c478bd9Sstevel@tonic-gate int len; 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate len = strlen(string); 1546*7c478bd9Sstevel@tonic-gate if ( write(Cn, string, (unsigned)len) != len ) 1547*7c478bd9Sstevel@tonic-gate VERBOSE(gettext(P_LINE_GONE),""); 1548*7c478bd9Sstevel@tonic-gate return; 1549*7c478bd9Sstevel@tonic-gate } 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1552*7c478bd9Sstevel@tonic-gate static void 1553*7c478bd9Sstevel@tonic-gate _onintrpt(sig) 1554*7c478bd9Sstevel@tonic-gate int sig; 1555*7c478bd9Sstevel@tonic-gate { 1556*7c478bd9Sstevel@tonic-gate (void)signal(SIGINT, _onintrpt); 1557*7c478bd9Sstevel@tonic-gate (void)signal(SIGQUIT, _onintrpt); 1558*7c478bd9Sstevel@tonic-gate Intrupt = YES; 1559*7c478bd9Sstevel@tonic-gate return; 1560*7c478bd9Sstevel@tonic-gate } 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate static void 1563*7c478bd9Sstevel@tonic-gate _rcvdead(arg) /* this is executed only in the receive process */ 1564*7c478bd9Sstevel@tonic-gate int arg; 1565*7c478bd9Sstevel@tonic-gate { 1566*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call _rcvdead(%d)\r\n", arg); 1567*7c478bd9Sstevel@tonic-gate (void)kill(getppid(), SIGUSR1); 1568*7c478bd9Sstevel@tonic-gate exit((arg == SIGHUP)? SIGHUP: arg); 1569*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate 1572*7c478bd9Sstevel@tonic-gate static void 1573*7c478bd9Sstevel@tonic-gate _quit(arg) /* this is executed only in the parent process */ 1574*7c478bd9Sstevel@tonic-gate int arg; 1575*7c478bd9Sstevel@tonic-gate { 1576*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call _quit(%d)\r\n", arg); 1577*7c478bd9Sstevel@tonic-gate (void)kill(Child, SIGKILL); 1578*7c478bd9Sstevel@tonic-gate _bye(arg); 1579*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1580*7c478bd9Sstevel@tonic-gate } 1581*7c478bd9Sstevel@tonic-gate 1582*7c478bd9Sstevel@tonic-gate static void 1583*7c478bd9Sstevel@tonic-gate _bye(arg) /* this is executed only in the parent proccess */ 1584*7c478bd9Sstevel@tonic-gate int arg; 1585*7c478bd9Sstevel@tonic-gate { 1586*7c478bd9Sstevel@tonic-gate int status; 1587*7c478bd9Sstevel@tonic-gate pid_t obit; 1588*7c478bd9Sstevel@tonic-gate 1589*7c478bd9Sstevel@tonic-gate if ( Shell > 0 ) 1590*7c478bd9Sstevel@tonic-gate while ((obit = wait(&status)) != Shell) { 1591*7c478bd9Sstevel@tonic-gate if (obit == -1 && errno != EINTR) 1592*7c478bd9Sstevel@tonic-gate break; 1593*7c478bd9Sstevel@tonic-gate /* _receive (Child) may have ended - check it out */ 1594*7c478bd9Sstevel@tonic-gate if (obit == Child) 1595*7c478bd9Sstevel@tonic-gate Child = 0; 1596*7c478bd9Sstevel@tonic-gate } 1597*7c478bd9Sstevel@tonic-gate 1598*7c478bd9Sstevel@tonic-gate /* give user customary message after escape command returns */ 1599*7c478bd9Sstevel@tonic-gate if (arg == SIGUSR1) 1600*7c478bd9Sstevel@tonic-gate VERBOSE("\r\nLost Carrier\r\n%s", ""); 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call _bye(%d)\r\n", arg); 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate (void)signal(SIGINT, SIG_IGN); 1605*7c478bd9Sstevel@tonic-gate (void)signal(SIGQUIT, SIG_IGN); 1606*7c478bd9Sstevel@tonic-gate /* if _receive() ended already, don't wait for it again */ 1607*7c478bd9Sstevel@tonic-gate if ( Child != 0 ) 1608*7c478bd9Sstevel@tonic-gate while ((obit = wait(&status)) != Child) 1609*7c478bd9Sstevel@tonic-gate if (obit == -1 && errno != EINTR) 1610*7c478bd9Sstevel@tonic-gate break; 1611*7c478bd9Sstevel@tonic-gate VERBOSE("\r\nDisconnected\007\r\n%s", ""); 1612*7c478bd9Sstevel@tonic-gate cleanup((arg == SIGUSR1)? (status >>= 8): arg); 1613*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1614*7c478bd9Sstevel@tonic-gate } 1615*7c478bd9Sstevel@tonic-gate 1616*7c478bd9Sstevel@tonic-gate 1617*7c478bd9Sstevel@tonic-gate 1618*7c478bd9Sstevel@tonic-gate void 1619*7c478bd9Sstevel@tonic-gate cleanup(code) /*this is executed only in the parent process*/ 1620*7c478bd9Sstevel@tonic-gate int code; /*Closes device; removes lock files */ 1621*7c478bd9Sstevel@tonic-gate { 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate CDEBUG(4,"call cleanup(%d)\r\n", code); 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate if (Docmd) { 1626*7c478bd9Sstevel@tonic-gate if (Child > 0) 1627*7c478bd9Sstevel@tonic-gate (void)kill(Child, SIGTERM); 1628*7c478bd9Sstevel@tonic-gate } else 1629*7c478bd9Sstevel@tonic-gate (void) setuid(Euid); 1630*7c478bd9Sstevel@tonic-gate if(Cn > 0) { 1631*7c478bd9Sstevel@tonic-gate fchmod(Cn, Dev_mode); 1632*7c478bd9Sstevel@tonic-gate fd_rmlock(Cn); 1633*7c478bd9Sstevel@tonic-gate (void)close(Cn); 1634*7c478bd9Sstevel@tonic-gate } 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate 1637*7c478bd9Sstevel@tonic-gate rmlock((char*) NULL); /* remove all lock files for this process */ 1638*7c478bd9Sstevel@tonic-gate if (!Docmd) 1639*7c478bd9Sstevel@tonic-gate _mode(0); 1640*7c478bd9Sstevel@tonic-gate exit(code); /* code=negative for signal causing disconnect*/ 1641*7c478bd9Sstevel@tonic-gate } 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate 1645*7c478bd9Sstevel@tonic-gate void 1646*7c478bd9Sstevel@tonic-gate tdmp(arg) 1647*7c478bd9Sstevel@tonic-gate int arg; 1648*7c478bd9Sstevel@tonic-gate { 1649*7c478bd9Sstevel@tonic-gate 1650*7c478bd9Sstevel@tonic-gate struct termio xv; 1651*7c478bd9Sstevel@tonic-gate int i; 1652*7c478bd9Sstevel@tonic-gate 1653*7c478bd9Sstevel@tonic-gate VERBOSE("\rdevice status for fd=%d\r\n", arg); 1654*7c478bd9Sstevel@tonic-gate VERBOSE("F_GETFL=%o,", fcntl(arg, F_GETFL,1)); 1655*7c478bd9Sstevel@tonic-gate if(ioctl(arg, TCGETA, &xv) < 0) { 1656*7c478bd9Sstevel@tonic-gate char buf[100]; 1657*7c478bd9Sstevel@tonic-gate i = errno; 1658*7c478bd9Sstevel@tonic-gate (void)snprintf(buf, sizeof (buf), gettext("\rtdmp for fd=%d"), arg); 1659*7c478bd9Sstevel@tonic-gate errno = i; 1660*7c478bd9Sstevel@tonic-gate perror(buf); 1661*7c478bd9Sstevel@tonic-gate return; 1662*7c478bd9Sstevel@tonic-gate } 1663*7c478bd9Sstevel@tonic-gate VERBOSE("iflag=`%o',", xv.c_iflag); 1664*7c478bd9Sstevel@tonic-gate VERBOSE("oflag=`%o',", xv.c_oflag); 1665*7c478bd9Sstevel@tonic-gate VERBOSE("cflag=`%o',", xv.c_cflag); 1666*7c478bd9Sstevel@tonic-gate VERBOSE("lflag=`%o',", xv.c_lflag); 1667*7c478bd9Sstevel@tonic-gate VERBOSE("line=`%o'\r\n", xv.c_line); 1668*7c478bd9Sstevel@tonic-gate VERBOSE("cc[0]=`%o',", xv.c_cc[0]); 1669*7c478bd9Sstevel@tonic-gate for(i=1; i<8; ++i) { 1670*7c478bd9Sstevel@tonic-gate VERBOSE("[%d]=", i); 1671*7c478bd9Sstevel@tonic-gate VERBOSE("`%o',",xv.c_cc[i]); 1672*7c478bd9Sstevel@tonic-gate } 1673*7c478bd9Sstevel@tonic-gate VERBOSE("\r\n%s", ""); 1674*7c478bd9Sstevel@tonic-gate return; 1675*7c478bd9Sstevel@tonic-gate } 1676*7c478bd9Sstevel@tonic-gate 1677*7c478bd9Sstevel@tonic-gate 1678*7c478bd9Sstevel@tonic-gate 1679*7c478bd9Sstevel@tonic-gate static void 1680*7c478bd9Sstevel@tonic-gate sysname(name) 1681*7c478bd9Sstevel@tonic-gate char * name; 1682*7c478bd9Sstevel@tonic-gate { 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate register char *s; 1685*7c478bd9Sstevel@tonic-gate 1686*7c478bd9Sstevel@tonic-gate if(uname(&utsn) < 0) 1687*7c478bd9Sstevel@tonic-gate s = "Local"; 1688*7c478bd9Sstevel@tonic-gate else 1689*7c478bd9Sstevel@tonic-gate s = utsn.nodename; 1690*7c478bd9Sstevel@tonic-gate 1691*7c478bd9Sstevel@tonic-gate strcpy(name, s); 1692*7c478bd9Sstevel@tonic-gate return; 1693*7c478bd9Sstevel@tonic-gate } 1694*7c478bd9Sstevel@tonic-gate 1695*7c478bd9Sstevel@tonic-gate 1696*7c478bd9Sstevel@tonic-gate static void 1697*7c478bd9Sstevel@tonic-gate blckcnt(count) 1698*7c478bd9Sstevel@tonic-gate long count; 1699*7c478bd9Sstevel@tonic-gate { 1700*7c478bd9Sstevel@tonic-gate static long lcharcnt = 0; 1701*7c478bd9Sstevel@tonic-gate register long c1, c2; 1702*7c478bd9Sstevel@tonic-gate register int i; 1703*7c478bd9Sstevel@tonic-gate char c; 1704*7c478bd9Sstevel@tonic-gate 1705*7c478bd9Sstevel@tonic-gate if(count == (long) (-1)) { /* initialization call */ 1706*7c478bd9Sstevel@tonic-gate lcharcnt = 0; 1707*7c478bd9Sstevel@tonic-gate return; 1708*7c478bd9Sstevel@tonic-gate } 1709*7c478bd9Sstevel@tonic-gate c1 = lcharcnt/BUFSIZ; 1710*7c478bd9Sstevel@tonic-gate if(count != (long)(-2)) { /* regular call */ 1711*7c478bd9Sstevel@tonic-gate c2 = count/BUFSIZ; 1712*7c478bd9Sstevel@tonic-gate for(i = c1; i++ < c2;) { 1713*7c478bd9Sstevel@tonic-gate c = '0' + i%10; 1714*7c478bd9Sstevel@tonic-gate write(2, &c, 1); 1715*7c478bd9Sstevel@tonic-gate if(i%NPL == 0) 1716*7c478bd9Sstevel@tonic-gate write(2, "\n\r", 2); 1717*7c478bd9Sstevel@tonic-gate } 1718*7c478bd9Sstevel@tonic-gate lcharcnt = count; 1719*7c478bd9Sstevel@tonic-gate } else { 1720*7c478bd9Sstevel@tonic-gate c2 = (lcharcnt + BUFSIZ -1)/BUFSIZ; 1721*7c478bd9Sstevel@tonic-gate if(c1 != c2) 1722*7c478bd9Sstevel@tonic-gate write(2, "+\n\r", 3); 1723*7c478bd9Sstevel@tonic-gate else if(c2%NPL != 0) 1724*7c478bd9Sstevel@tonic-gate write(2, "\n\r", 2); 1725*7c478bd9Sstevel@tonic-gate lcharcnt = 0; 1726*7c478bd9Sstevel@tonic-gate } 1727*7c478bd9Sstevel@tonic-gate return; 1728*7c478bd9Sstevel@tonic-gate } 1729*7c478bd9Sstevel@tonic-gate 1730*7c478bd9Sstevel@tonic-gate /*VARARGS*/ 1731*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1732*7c478bd9Sstevel@tonic-gate void 1733*7c478bd9Sstevel@tonic-gate assert (s1, s2, i1, s3, i2) 1734*7c478bd9Sstevel@tonic-gate char *s1, *s2, *s3; 1735*7c478bd9Sstevel@tonic-gate int i1, i2; 1736*7c478bd9Sstevel@tonic-gate { } /* for ASSERT in gnamef.c */ 1737*7c478bd9Sstevel@tonic-gate 1738*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1739*7c478bd9Sstevel@tonic-gate void 1740*7c478bd9Sstevel@tonic-gate logent (s1, s2) 1741*7c478bd9Sstevel@tonic-gate char *s1, *s2; 1742*7c478bd9Sstevel@tonic-gate { } /* so we can load ulockf() */ 1743