1161754Sru/*	$OpenBSD: tip.c,v 1.30 2006/08/18 03:06:18 jason Exp $	*/
288276Smarkm/*	$NetBSD: tip.c,v 1.13 1997/04/20 00:03:05 mellon Exp $	*/
388276Smarkm
47527Sjkh/*
57527Sjkh * Copyright (c) 1983, 1993
67527Sjkh *	The Regents of the University of California.  All rights reserved.
77527Sjkh *
87527Sjkh * Redistribution and use in source and binary forms, with or without
97527Sjkh * modification, are permitted provided that the following conditions
107527Sjkh * are met:
117527Sjkh * 1. Redistributions of source code must retain the above copyright
127527Sjkh *    notice, this list of conditions and the following disclaimer.
137527Sjkh * 2. Redistributions in binary form must reproduce the above copyright
147527Sjkh *    notice, this list of conditions and the following disclaimer in the
157527Sjkh *    documentation and/or other materials provided with the distribution.
16161754Sru * 3. Neither the name of the University nor the names of its contributors
177527Sjkh *    may be used to endorse or promote products derived from this software
187527Sjkh *    without specific prior written permission.
197527Sjkh *
207527Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217527Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227527Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237527Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247527Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257527Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267527Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277527Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287527Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297527Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307527Sjkh * SUCH DAMAGE.
317527Sjkh */
327527Sjkh
3388276Smarkm#include <sys/cdefs.h>
3488276Smarkm__FBSDID("$FreeBSD: releng/10.3/usr.bin/tip/tip/tip.c 230654 2012-01-28 20:45:47Z phk $");
3588276Smarkm
367527Sjkh#ifndef lint
37161754Srustatic const char copyright[] =
387527Sjkh"@(#) Copyright (c) 1983, 1993\n\
397527Sjkh	The Regents of the University of California.  All rights reserved.\n";
407527Sjkh#endif /* not lint */
417527Sjkh
427527Sjkh#ifndef lint
4328365Scharnier#if 0
447527Sjkhstatic char sccsid[] = "@(#)tip.c	8.1 (Berkeley) 6/6/93";
45161754Srustatic const char rcsid[] = "$OpenBSD: tip.c,v 1.30 2006/08/18 03:06:18 jason Exp $";
4628365Scharnier#endif
477527Sjkh#endif /* not lint */
487527Sjkh
497527Sjkh/*
507527Sjkh * tip - UNIX link to other systems
517527Sjkh *  tip [-v] [-speed] system-name
527527Sjkh * or
537527Sjkh *  cu phone-number [-s speed] [-l line] [-a acu]
547527Sjkh */
557527Sjkh#include "tip.h"
567527Sjkh#include "pathnames.h"
577527Sjkh
5888276Smarkmint	disc = TTYDISC;		/* tip normally runs this way */
597527Sjkhchar	PNbuf[256];			/* This limits the size of a number */
607527Sjkh
61161754Srustatic void	intprompt(int);
62161754Srustatic void	tipin(void);
63161754Srustatic int	escape(void);
64161754Sru
6551287Speterint
66161754Srumain(int argc, char *argv[])
677527Sjkh{
68161754Sru	char *sys = NOSTR, sbuf[12], *p;
6988276Smarkm	int i;
707527Sjkh
71161754Sru	/* XXX preserve previous braindamaged behavior */
72161754Sru	setboolean(value(DC), TRUE);
73161754Sru
747527Sjkh	gid = getgid();
757527Sjkh	egid = getegid();
767527Sjkh	uid = getuid();
777527Sjkh	euid = geteuid();
7888276Smarkm	if (equal(__progname, "cu")) {
797527Sjkh		cumode = 1;
807527Sjkh		cumain(argc, argv);
817527Sjkh		goto cucommon;
827527Sjkh	}
837527Sjkh
8488276Smarkm	if (argc > 4) {
8588276Smarkm		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
8688276Smarkm		exit(1);
8788276Smarkm	}
8888276Smarkm	if (!isatty(0)) {
8988276Smarkm		fprintf(stderr, "%s: must be interactive\n", __progname);
9088276Smarkm		exit(1);
9188276Smarkm	}
927527Sjkh
937527Sjkh	for (; argc > 1; argv++, argc--) {
947527Sjkh		if (argv[1][0] != '-')
95161754Sru			sys = argv[1];
967527Sjkh		else switch (argv[1][1]) {
977527Sjkh
987527Sjkh		case 'v':
997527Sjkh			vflag++;
1007527Sjkh			break;
1017527Sjkh
10288276Smarkm		case 'n':
10388276Smarkm			noesc++;
10488276Smarkm			break;
10588276Smarkm
1067527Sjkh		case '0': case '1': case '2': case '3': case '4':
1077527Sjkh		case '5': case '6': case '7': case '8': case '9':
1087527Sjkh			BR = atoi(&argv[1][1]);
1097527Sjkh			break;
1107527Sjkh
1117527Sjkh		default:
11288276Smarkm			fprintf(stderr, "%s: %s, unknown option\n", __progname,
11388276Smarkm			    argv[1]);
1147527Sjkh			break;
1157527Sjkh		}
1167527Sjkh	}
1177527Sjkh
118161754Sru	if (sys == NOSTR)
1197527Sjkh		goto notnumber;
120161754Sru	if (isalpha(*sys))
1217527Sjkh		goto notnumber;
1227527Sjkh	/*
1237527Sjkh	 * System name is really a phone number...
1247527Sjkh	 * Copy the number then stomp on the original (in case the number
1257527Sjkh	 *	is private, we don't want 'ps' or 'w' to find it).
1267527Sjkh	 */
127161754Sru	if (strlen(sys) > sizeof PNbuf - 1) {
12888276Smarkm		fprintf(stderr, "%s: phone number too long (max = %d bytes)\n",
12988276Smarkm			__progname, (int)sizeof(PNbuf) - 1);
13088276Smarkm		exit(1);
13188276Smarkm	}
132161754Sru	strlcpy(PNbuf, sys, sizeof PNbuf - 1);
133161754Sru	for (p = sys; *p; p++)
1347527Sjkh		*p = '\0';
1357527Sjkh	PN = PNbuf;
13636791Simp	(void)snprintf(sbuf, sizeof(sbuf), "tip%ld", BR);
137161754Sru	sys = sbuf;
1387527Sjkh
1397527Sjkhnotnumber:
1407527Sjkh	(void)signal(SIGINT, cleanup);
1417527Sjkh	(void)signal(SIGQUIT, cleanup);
1427527Sjkh	(void)signal(SIGHUP, cleanup);
1437527Sjkh	(void)signal(SIGTERM, cleanup);
144161754Sru	(void)signal(SIGCHLD, SIG_DFL);
1457527Sjkh
146161754Sru	if ((i = hunt(sys)) == 0) {
1477527Sjkh		printf("all ports busy\n");
1487527Sjkh		exit(3);
1497527Sjkh	}
1507527Sjkh	if (i == -1) {
1517527Sjkh		printf("link down\n");
1527527Sjkh		(void)uu_unlock(uucplock);
1537527Sjkh		exit(3);
1547527Sjkh	}
1557527Sjkh	setbuf(stdout, NULL);
1567527Sjkh	loginit();
1577527Sjkh
1587527Sjkh	/*
15988276Smarkm	 * Now that we have the logfile and the ACU open
16088276Smarkm	 *  return to the real uid and gid.  These things will
16188276Smarkm	 *  be closed on exit.  Swap real and effective uid's
16288276Smarkm	 *  so we can get the original permissions back
16388276Smarkm	 *  for removing the uucp lock.
16488276Smarkm	 */
16588276Smarkm	user_uid();
16688276Smarkm
16788276Smarkm	/*
1687527Sjkh	 * Kludge, their's no easy way to get the initialization
1697527Sjkh	 *   in the right order, so force it here
1707527Sjkh	 */
1717527Sjkh	if ((PH = getenv("PHONES")) == NOSTR)
1727527Sjkh		PH = _PATH_PHONES;
1737527Sjkh	vinit();				/* init variables */
17488276Smarkm	setparity("none");			/* set the parity table */
1757527Sjkh
1767527Sjkh	/*
1777527Sjkh	 * Hardwired connections require the
1787527Sjkh	 *  line speed set before they make any transmissions
1797527Sjkh	 *  (this is particularly true of things like a DF03-AC)
1807527Sjkh	 */
181161754Sru	if (HW && ttysetup(number(value(BAUDRATE)))) {
182161754Sru		fprintf(stderr, "%s: bad baud rate %ld\n", __progname,
183161754Sru		    number(value(BAUDRATE)));
1847527Sjkh		daemon_uid();
1857527Sjkh		(void)uu_unlock(uucplock);
186161754Sru		exit(3);
187161754Sru	}
188161754Sru	if ((p = con())) {
189161754Sru		printf("\07%s\n[EOT]\n", p);
190161754Sru		daemon_uid();
191161754Sru		(void)uu_unlock(uucplock);
1927527Sjkh		exit(1);
1937527Sjkh	}
194161754Sru	if (!HW && ttysetup(number(value(BAUDRATE)))) {
195161754Sru		fprintf(stderr, "%s: bad baud rate %ld\n", __progname,
196161754Sru		    number(value(BAUDRATE)));
197161754Sru		daemon_uid();
198161754Sru		(void)uu_unlock(uucplock);
199161754Sru		exit(3);
200161754Sru	}
20188276Smarkmcucommon:
2027527Sjkh	/*
2037527Sjkh	 * From here down the code is shared with
2047527Sjkh	 * the "cu" version of tip.
2057527Sjkh	 */
2067527Sjkh
20788276Smarkm	i = fcntl(FD, F_GETFL);
20888276Smarkm	if (i == -1) {
20988276Smarkm		perror("fcntl");
210161754Sru		cleanup(0);
21188276Smarkm	}
21288276Smarkm	i = fcntl(FD, F_SETFL, i & ~O_NONBLOCK);
21388276Smarkm	if (i == -1) {
21488276Smarkm		perror("fcntl");
215161754Sru		cleanup(0);
21688276Smarkm	}
21788276Smarkm
21888276Smarkm	tcgetattr(0, &defterm);
219161754Sru	gotdefterm = 1;
22088276Smarkm	term = defterm;
22188276Smarkm	term.c_lflag &= ~(ICANON|IEXTEN|ECHO);
22288276Smarkm	term.c_iflag &= ~(INPCK|ICRNL);
22388276Smarkm	term.c_oflag &= ~OPOST;
22488276Smarkm	term.c_cc[VMIN] = 1;
22588276Smarkm	term.c_cc[VTIME] = 0;
22688276Smarkm	defchars = term;
22788276Smarkm	term.c_cc[VINTR] = term.c_cc[VQUIT] = term.c_cc[VSUSP] =
228161754Sru	    term.c_cc[VDSUSP] = term.c_cc[VDISCARD] =
229161754Sru	    term.c_cc[VLNEXT] = _POSIX_VDISABLE;
2307527Sjkh	raw();
2317527Sjkh
2327527Sjkh	pipe(fildes); pipe(repdes);
2337527Sjkh	(void)signal(SIGALRM, timeout);
2347527Sjkh
235161754Sru	if (value(LINEDISC) != TTYDISC) {
236161781Sru		int ld = (int)(intptr_t)value(LINEDISC);
237161754Sru		ioctl(FD, TIOCSETD, &ld);
238161754Sru	}
239161754Sru
2407527Sjkh	/*
2417527Sjkh	 * Everything's set up now:
2427527Sjkh	 *	connection established (hardwired or dialup)
2437527Sjkh	 *	line conditioned (baud rate, mode, etc.)
2447527Sjkh	 *	internal data structures (variables)
2457527Sjkh	 * so, fork one process for local side and one for remote.
2467527Sjkh	 */
2477527Sjkh	printf(cumode ? "Connected\r\n" : "\07connected\r\n");
248161754Sru	tipin_pid = getpid();
249161754Sru	if ((tipout_pid = fork()))
2507527Sjkh		tipin();
2517527Sjkh	else
2527527Sjkh		tipout();
2537527Sjkh	/*NOTREACHED*/
25488276Smarkm	exit(0);
2557527Sjkh}
2567527Sjkh
2577527Sjkhvoid
258161754Srucleanup(int signo)
2597527Sjkh{
2607527Sjkh	daemon_uid();
2617527Sjkh	(void)uu_unlock(uucplock);
2627527Sjkh	if (odisc)
263161754Sru		ioctl(0, TIOCSETD, &odisc);
264161754Sru	unraw();
265161754Sru	if (signo && tipout_pid) {
266161754Sru		kill(tipout_pid, signo);
267161754Sru		wait(NULL);
268161754Sru	}
2697527Sjkh	exit(0);
2707527Sjkh}
2717527Sjkh
2727527Sjkh/*
2737527Sjkh * Muck with user ID's.  We are setuid to the owner of the lock
2747527Sjkh * directory when we start.  user_uid() reverses real and effective
2757527Sjkh * ID's after startup, to run with the user's permissions.
2767527Sjkh * daemon_uid() switches back to the privileged uid for unlocking.
2777527Sjkh * Finally, to avoid running a shell with the wrong real uid,
2787527Sjkh * shell_uid() sets real and effective uid's to the user's real ID.
2797527Sjkh */
2807527Sjkhstatic int uidswapped;
2817527Sjkh
28228365Scharniervoid
283161754Sruuser_uid(void)
2847527Sjkh{
2857527Sjkh	if (uidswapped == 0) {
2867527Sjkh		seteuid(uid);
2877527Sjkh		uidswapped = 1;
2887527Sjkh	}
2897527Sjkh}
2907527Sjkh
29128365Scharniervoid
292161754Srudaemon_uid(void)
2937527Sjkh{
29488276Smarkm
2957527Sjkh	if (uidswapped) {
2967527Sjkh		seteuid(euid);
2977527Sjkh		uidswapped = 0;
2987527Sjkh	}
2997527Sjkh}
3007527Sjkh
30128365Scharniervoid
302161754Srushell_uid(void)
3037527Sjkh{
30436791Simp	setegid(gid);
3057527Sjkh	seteuid(uid);
3067527Sjkh}
3077527Sjkh
3087527Sjkh/*
3097527Sjkh * put the controlling keyboard into raw mode
3107527Sjkh */
3117527Sjkhvoid
312161754Sruraw(void)
3137527Sjkh{
31488276Smarkm	tcsetattr(0, TCSADRAIN, &term);
3157527Sjkh}
3167527Sjkh
3177527Sjkh
3187527Sjkh/*
3197527Sjkh * return keyboard to normal mode
3207527Sjkh */
32128365Scharniervoid
322161754Sruunraw(void)
3237527Sjkh{
324161754Sru	if (gotdefterm)
325161754Sru		tcsetattr(0, TCSADRAIN, &defterm);
3267527Sjkh}
3277527Sjkh
328178736Sbms/*
329178736Sbms * give up exclusive tty access
330178736Sbms */
331178736Sbmsvoid
332178736Sbmsunexcl()
333178736Sbms{
334178736Sbms	ioctl(FD, TIOCNXCL, 0);
335178736Sbms}
336178736Sbms
3377527Sjkhstatic	jmp_buf promptbuf;
3387527Sjkh
3397527Sjkh/*
3407527Sjkh * Print string ``s'', then read a string
3417527Sjkh *  in from the terminal.  Handles signals & allows use of
3427527Sjkh *  normal erase and kill characters.
3437527Sjkh */
34428365Scharnierint
345161754Sruprompt(char *s, char *p, size_t sz)
3467527Sjkh{
34788276Smarkm	int c;
34888276Smarkm	char *b = p;
3497527Sjkh	sig_t oint, oquit;
3507527Sjkh
3517527Sjkh	stoprompt = 0;
3527527Sjkh	oint = signal(SIGINT, intprompt);
3537527Sjkh	oquit = signal(SIGQUIT, SIG_IGN);
3547527Sjkh	unraw();
3557527Sjkh	printf("%s", s);
3567527Sjkh	if (setjmp(promptbuf) == 0)
35788276Smarkm		while ((c = getchar()) != EOF && (*p = c) != '\n' && --sz > 0)
3587527Sjkh			p++;
3597527Sjkh	*p = '\0';
3607527Sjkh
3617527Sjkh	raw();
3627527Sjkh	(void)signal(SIGINT, oint);
3637527Sjkh	(void)signal(SIGQUIT, oquit);
3647527Sjkh	return (stoprompt || p == b);
3657527Sjkh}
3667527Sjkh
3677527Sjkh/*
3687527Sjkh * Interrupt service routine during prompting
3697527Sjkh */
370161754Sru/*ARGSUSED*/
371161754Srustatic void
372161754Sruintprompt(int signo)
3737527Sjkh{
3747527Sjkh	(void)signal(SIGINT, SIG_IGN);
3757527Sjkh	stoprompt = 1;
3767527Sjkh	printf("\r\n");
3777527Sjkh	longjmp(promptbuf, 1);
3787527Sjkh}
3797527Sjkh
3807527Sjkh/*
3817527Sjkh * ****TIPIN   TIPIN****
3827527Sjkh */
383161754Srustatic void
384161754Srutipin(void)
3857527Sjkh{
386161754Sru	int bol = 1;
387161754Sru	int gch;
388161754Sru	char ch;
3897527Sjkh
3907527Sjkh	/*
3917527Sjkh	 * Kinda klugey here...
3927527Sjkh	 *   check for scripting being turned on from the .tiprc file,
3937527Sjkh	 *   but be careful about just using setscript(), as we may
3947527Sjkh	 *   send a SIGEMT before tipout has a chance to set up catching
3957527Sjkh	 *   it; so wait a second, then setscript()
3967527Sjkh	 */
3977527Sjkh	if (boolean(value(SCRIPT))) {
3987527Sjkh		sleep(1);
3997527Sjkh		setscript();
4007527Sjkh	}
4017527Sjkh
4027527Sjkh	while (1) {
40388276Smarkm		gch = getchar()&STRIP_PAR;
404161754Sru		/* XXX does not check for EOF */
4057527Sjkh		if ((gch == character(value(ESCAPE))) && bol) {
40688276Smarkm			if (!noesc) {
40788276Smarkm				if (!(gch = escape()))
40888276Smarkm					continue;
40988276Smarkm			}
4107527Sjkh		} else if (!cumode && gch == character(value(RAISECHAR))) {
41188276Smarkm			setboolean(value(RAISE), !boolean(value(RAISE)));
4127527Sjkh			continue;
4137527Sjkh		} else if (gch == '\r') {
4147527Sjkh			bol = 1;
415161754Sru			ch = gch;
416161754Sru			parwrite(FD, &ch, 1);
4177527Sjkh			if (boolean(value(HALFDUPLEX)))
4187527Sjkh				printf("\r\n");
4197527Sjkh			continue;
42088276Smarkm		} else if (!cumode && gch == character(value(FORCE)))
42188276Smarkm			gch = getchar()&STRIP_PAR;
4227527Sjkh		bol = any(gch, value(EOL));
4237527Sjkh		if (boolean(value(RAISE)) && islower(gch))
4247527Sjkh			gch = toupper(gch);
425161754Sru		ch = gch;
426161754Sru		parwrite(FD, &ch, 1);
4277527Sjkh		if (boolean(value(HALFDUPLEX)))
428161754Sru			printf("%c", ch);
4297527Sjkh	}
4307527Sjkh}
4317527Sjkh
4327527Sjkhextern esctable_t etable[];
4337527Sjkh
4347527Sjkh/*
4357527Sjkh * Escape handler --
4367527Sjkh *  called on recognition of ``escapec'' at the beginning of a line
4377527Sjkh */
438161754Srustatic int
439161754Sruescape(void)
4407527Sjkh{
441161754Sru	int gch;
44288276Smarkm	esctable_t *p;
4437527Sjkh	char c = character(value(ESCAPE));
4447527Sjkh
44588276Smarkm	gch = (getchar()&STRIP_PAR);
446161754Sru	/* XXX does not check for EOF */
4477527Sjkh	for (p = etable; p->e_char; p++)
4487527Sjkh		if (p->e_char == gch) {
4497527Sjkh			if ((p->e_flags&PRIV) && uid)
4507527Sjkh				continue;
4517527Sjkh			printf("%s", ctrl(c));
4527527Sjkh			(*p->e_func)(gch);
4537527Sjkh			return (0);
4547527Sjkh		}
4557527Sjkh	/* ESCAPE ESCAPE forces ESCAPE */
4567527Sjkh	if (c != gch)
45788276Smarkm		parwrite(FD, &c, 1);
4587527Sjkh	return (gch);
4597527Sjkh}
4607527Sjkh
46128365Scharnierint
462161754Sruany(int cc, char *p)
4637527Sjkh{
46488276Smarkm	char c = cc;
4657527Sjkh	while (p && *p)
4667527Sjkh		if (*p++ == c)
4677527Sjkh			return (1);
4687527Sjkh	return (0);
4697527Sjkh}
4707527Sjkh
471161754Srusize_t
472161754Srusize(char *s)
4737527Sjkh{
474161754Sru	size_t i = 0;
4757527Sjkh
4767527Sjkh	while (s && *s++)
4777527Sjkh		i++;
4787527Sjkh	return (i);
4797527Sjkh}
4807527Sjkh
4817527Sjkhchar *
482161754Sruinterp(char *s)
4837527Sjkh{
4847527Sjkh	static char buf[256];
48588276Smarkm	char *p = buf, c, *q;
4867527Sjkh
48728365Scharnier	while ((c = *s++)) {
4887527Sjkh		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
4897527Sjkh			if (*q++ == c) {
4907527Sjkh				*p++ = '\\'; *p++ = *q;
4917527Sjkh				goto next;
4927527Sjkh			}
4937527Sjkh		if (c < 040) {
4947527Sjkh			*p++ = '^'; *p++ = c + 'A'-1;
4957527Sjkh		} else if (c == 0177) {
4967527Sjkh			*p++ = '^'; *p++ = '?';
4977527Sjkh		} else
4987527Sjkh			*p++ = c;
4997527Sjkh	next:
5007527Sjkh		;
5017527Sjkh	}
5027527Sjkh	*p = '\0';
5037527Sjkh	return (buf);
5047527Sjkh}
5057527Sjkh
5067527Sjkhchar *
507161754Sructrl(char c)
5087527Sjkh{
5097527Sjkh	static char s[3];
5107527Sjkh
5117527Sjkh	if (c < 040 || c == 0177) {
5127527Sjkh		s[0] = '^';
5137527Sjkh		s[1] = c == 0177 ? '?' : c+'A'-1;
5147527Sjkh		s[2] = '\0';
5157527Sjkh	} else {
5167527Sjkh		s[0] = c;
5177527Sjkh		s[1] = '\0';
5187527Sjkh	}
5197527Sjkh	return (s);
5207527Sjkh}
5217527Sjkh
5227527Sjkh/*
5237527Sjkh * Help command
5247527Sjkh */
52528365Scharniervoid
526161754Sruhelp(int c)
5277527Sjkh{
52888276Smarkm	esctable_t *p;
5297527Sjkh
5307527Sjkh	printf("%c\r\n", c);
5317527Sjkh	for (p = etable; p->e_char; p++) {
5327527Sjkh		if ((p->e_flags&PRIV) && uid)
5337527Sjkh			continue;
5347527Sjkh		printf("%2s", ctrl(character(value(ESCAPE))));
5357527Sjkh		printf("%-2s %c   %s\r\n", ctrl(p->e_char),
5367527Sjkh			p->e_flags&EXP ? '*': ' ', p->e_help);
5377527Sjkh	}
5387527Sjkh}
5397527Sjkh
5407527Sjkh/*
5417527Sjkh * Set up the "remote" tty's state
5427527Sjkh */
543161754Sruint
544161754Sruttysetup(int speed)
5457527Sjkh{
54688276Smarkm	struct termios	cntrl;
5477527Sjkh
548161754Sru	if (tcgetattr(FD, &cntrl))
549161754Sru		return (-1);
550161754Sru	cfsetspeed(&cntrl, speed);
55188276Smarkm	cntrl.c_cflag &= ~(CSIZE|PARENB);
55288276Smarkm	cntrl.c_cflag |= CS8;
55388276Smarkm	if (boolean(value(DC)))
55488276Smarkm		cntrl.c_cflag |= CLOCAL;
555161754Sru	if (boolean(value(HARDWAREFLOW)))
556161754Sru		cntrl.c_cflag |= CRTSCTS;
55788276Smarkm	cntrl.c_iflag &= ~(ISTRIP|ICRNL);
55888276Smarkm	cntrl.c_oflag &= ~OPOST;
55988276Smarkm	cntrl.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
56088276Smarkm	cntrl.c_cc[VMIN] = 1;
56188276Smarkm	cntrl.c_cc[VTIME] = 0;
5627527Sjkh	if (boolean(value(TAND)))
56388276Smarkm		cntrl.c_iflag |= IXOFF;
564161754Sru	return (tcsetattr(FD, TCSAFLUSH, &cntrl));
5657527Sjkh}
5667527Sjkh
5677527Sjkhstatic char partab[0200];
5687527Sjkh
5697527Sjkh/*
5707527Sjkh * Do a write to the remote machine with the correct parity.
5717527Sjkh * We are doing 8 bit wide output, so we just generate a character
5727527Sjkh * with the right parity and output it.
5737527Sjkh */
57428365Scharniervoid
575161754Sruparwrite(int fd, char *buf, size_t n)
5767527Sjkh{
577161781Sru	size_t i;
57888276Smarkm	char *bp;
5797527Sjkh
5807527Sjkh	bp = buf;
5817527Sjkh	if (bits8 == 0)
5827527Sjkh		for (i = 0; i < n; i++) {
5837527Sjkh			*bp = partab[(*bp) & 0177];
5847527Sjkh			bp++;
5857527Sjkh		}
5867527Sjkh	if (write(fd, buf, n) < 0) {
587230654Sphk		if (errno == EIO || errno == ENXIO)
5887527Sjkh			tipabort("Lost carrier.");
58988276Smarkm		/* this is questionable */
59088276Smarkm		perror("write");
5917527Sjkh	}
5927527Sjkh}
5937527Sjkh
5947527Sjkh/*
5957527Sjkh * Build a parity table with appropriate high-order bit.
5967527Sjkh */
59728365Scharniervoid
598161754Srusetparity(char *defparity)
5997527Sjkh{
60088276Smarkm	int i, flip, clr, set;
6017527Sjkh	char *parity;
60288276Smarkm	extern const unsigned char evenpartab[];
6037527Sjkh
6047527Sjkh	if (value(PARITY) == NOSTR)
6057527Sjkh		value(PARITY) = defparity;
6067527Sjkh	parity = value(PARITY);
6077527Sjkh	if (equal(parity, "none")) {
6087527Sjkh		bits8 = 1;
6097527Sjkh		return;
6107527Sjkh	}
6117527Sjkh	bits8 = 0;
6127527Sjkh	flip = 0;
6137527Sjkh	clr = 0377;
6147527Sjkh	set = 0;
6157527Sjkh	if (equal(parity, "odd"))
6167527Sjkh		flip = 0200;			/* reverse bit 7 */
6177527Sjkh	else if (equal(parity, "zero"))
6187527Sjkh		clr = 0177;			/* turn off bit 7 */
6197527Sjkh	else if (equal(parity, "one"))
6207527Sjkh		set = 0200;			/* turn on bit 7 */
6217527Sjkh	else if (!equal(parity, "even")) {
6227527Sjkh		(void) fprintf(stderr, "%s: unknown parity value\r\n", parity);
6237527Sjkh		(void) fflush(stderr);
6247527Sjkh	}
6257527Sjkh	for (i = 0; i < 0200; i++)
626161754Sru		partab[i] = ((evenpartab[i] ^ flip) | set) & clr;
6277527Sjkh}
628