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