11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1991, 1993, 1994
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * Redistribution and use in source and binary forms, with or without
61556Srgrimes * modification, are permitted provided that the following conditions
71556Srgrimes * are met:
81556Srgrimes * 1. Redistributions of source code must retain the above copyright
91556Srgrimes *    notice, this list of conditions and the following disclaimer.
101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111556Srgrimes *    notice, this list of conditions and the following disclaimer in the
121556Srgrimes *    documentation and/or other materials provided with the distribution.
131556Srgrimes * 4. Neither the name of the University nor the names of its contributors
141556Srgrimes *    may be used to endorse or promote products derived from this software
151556Srgrimes *    without specific prior written permission.
161556Srgrimes *
171556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271556Srgrimes * SUCH DAMAGE.
281556Srgrimes */
291556Srgrimes
301556Srgrimes#ifndef lint
3128642Ssteve#if 0
3228642Sstevestatic char sccsid[] = "@(#)key.c	8.3 (Berkeley) 4/2/94";
3328642Ssteve#endif
341556Srgrimes#endif /* not lint */
3599110Sobrien#include <sys/cdefs.h>
3699110Sobrien__FBSDID("$FreeBSD$");
371556Srgrimes
381556Srgrimes#include <sys/types.h>
391556Srgrimes
401556Srgrimes#include <err.h>
411556Srgrimes#include <errno.h>
421556Srgrimes#include <stdlib.h>
431556Srgrimes#include <stdio.h>
441556Srgrimes#include <string.h>
451556Srgrimes
461556Srgrimes#include "stty.h"
471556Srgrimes#include "extern.h"
481556Srgrimes
491556Srgrimes__BEGIN_DECLS
5090111Simpstatic int c_key(const void *, const void *);
5190111Simpvoid	f_all(struct info *);
5290111Simpvoid	f_cbreak(struct info *);
5390111Simpvoid	f_columns(struct info *);
5490111Simpvoid	f_dec(struct info *);
5590111Simpvoid	f_ek(struct info *);
5690111Simpvoid	f_everything(struct info *);
5790111Simpvoid	f_extproc(struct info *);
5890111Simpvoid	f_ispeed(struct info *);
5990111Simpvoid	f_nl(struct info *);
6090111Simpvoid	f_ospeed(struct info *);
6190111Simpvoid	f_raw(struct info *);
6290111Simpvoid	f_rows(struct info *);
6390111Simpvoid	f_sane(struct info *);
6490111Simpvoid	f_size(struct info *);
6590111Simpvoid	f_speed(struct info *);
6690111Simpvoid	f_tty(struct info *);
671556Srgrimes__END_DECLS
681556Srgrimes
691556Srgrimesstatic struct key {
7076810Skris	const char *name;			/* name */
7190111Simp	void (*f)(struct info *);		/* function */
721556Srgrimes#define	F_NEEDARG	0x01			/* needs an argument */
731556Srgrimes#define	F_OFFOK		0x02			/* can turn off */
741556Srgrimes	int flags;
751556Srgrimes} keys[] = {
761556Srgrimes	{ "all",	f_all,		0 },
771556Srgrimes	{ "cbreak",	f_cbreak,	F_OFFOK },
781556Srgrimes	{ "cols",	f_columns,	F_NEEDARG },
791556Srgrimes	{ "columns",	f_columns,	F_NEEDARG },
801556Srgrimes	{ "cooked", 	f_sane,		0 },
811556Srgrimes	{ "dec",	f_dec,		0 },
8282237Sdd	{ "ek",		f_ek,		0 },
831556Srgrimes	{ "everything",	f_everything,	0 },
841556Srgrimes	{ "extproc",	f_extproc,	F_OFFOK },
851556Srgrimes	{ "ispeed",	f_ispeed,	F_NEEDARG },
861556Srgrimes	{ "new",	f_tty,		0 },
871556Srgrimes	{ "nl",		f_nl,		F_OFFOK },
881556Srgrimes	{ "old",	f_tty,		0 },
891556Srgrimes	{ "ospeed",	f_ospeed,	F_NEEDARG },
901556Srgrimes	{ "raw",	f_raw,		F_OFFOK },
911556Srgrimes	{ "rows",	f_rows,		F_NEEDARG },
921556Srgrimes	{ "sane",	f_sane,		0 },
931556Srgrimes	{ "size",	f_size,		0 },
941556Srgrimes	{ "speed",	f_speed,	0 },
951556Srgrimes	{ "tty",	f_tty,		0 },
961556Srgrimes};
971556Srgrimes
981556Srgrimesstatic int
9990111Simpc_key(const void *a, const void *b)
1001556Srgrimes{
1011556Srgrimes
10276810Skris        return (strcmp(((const struct key *)a)->name, ((const struct key *)b)->name));
1031556Srgrimes}
1041556Srgrimes
1051556Srgrimesint
10690111Simpksearch(char ***argvp, struct info *ip)
1071556Srgrimes{
1081556Srgrimes	char *name;
1091556Srgrimes	struct key *kp, tmp;
1101556Srgrimes
1111556Srgrimes	name = **argvp;
1121556Srgrimes	if (*name == '-') {
1131556Srgrimes		ip->off = 1;
1141556Srgrimes		++name;
1151556Srgrimes	} else
1161556Srgrimes		ip->off = 0;
1171556Srgrimes
1181556Srgrimes	tmp.name = name;
1191556Srgrimes	if (!(kp = (struct key *)bsearch(&tmp, keys,
1201556Srgrimes	    sizeof(keys)/sizeof(struct key), sizeof(struct key), c_key)))
1211556Srgrimes		return (0);
1221556Srgrimes	if (!(kp->flags & F_OFFOK) && ip->off) {
12328642Ssteve		warnx("illegal option -- -%s", name);
1241556Srgrimes		usage();
1251556Srgrimes	}
1261556Srgrimes	if (kp->flags & F_NEEDARG && !(ip->arg = *++*argvp)) {
12728642Ssteve		warnx("option requires an argument -- %s", name);
1281556Srgrimes		usage();
1291556Srgrimes	}
1301556Srgrimes	kp->f(ip);
1311556Srgrimes	return (1);
1321556Srgrimes}
1331556Srgrimes
1341556Srgrimesvoid
13590111Simpf_all(struct info *ip)
1361556Srgrimes{
13759788Sache	print(&ip->t, &ip->win, ip->ldisc, BSD);
1381556Srgrimes}
1391556Srgrimes
1401556Srgrimesvoid
14190111Simpf_cbreak(struct info *ip)
1421556Srgrimes{
1431556Srgrimes
1441556Srgrimes	if (ip->off)
1451556Srgrimes		f_sane(ip);
1461556Srgrimes	else {
1471556Srgrimes		ip->t.c_iflag |= BRKINT|IXON|IMAXBEL;
1481556Srgrimes		ip->t.c_oflag |= OPOST;
1491556Srgrimes		ip->t.c_lflag |= ISIG|IEXTEN;
1501556Srgrimes		ip->t.c_lflag &= ~ICANON;
1511556Srgrimes		ip->set = 1;
1521556Srgrimes	}
1531556Srgrimes}
1541556Srgrimes
1551556Srgrimesvoid
15690111Simpf_columns(struct info *ip)
1571556Srgrimes{
1581556Srgrimes
1591556Srgrimes	ip->win.ws_col = atoi(ip->arg);
1601556Srgrimes	ip->wset = 1;
1611556Srgrimes}
1621556Srgrimes
1631556Srgrimesvoid
16490111Simpf_dec(struct info *ip)
1651556Srgrimes{
1661556Srgrimes
1671556Srgrimes	ip->t.c_cc[VERASE] = (u_char)0177;
1681556Srgrimes	ip->t.c_cc[VKILL] = CTRL('u');
1691556Srgrimes	ip->t.c_cc[VINTR] = CTRL('c');
1701556Srgrimes	ip->t.c_lflag &= ~ECHOPRT;
1711556Srgrimes	ip->t.c_lflag |= ECHOE|ECHOKE|ECHOCTL;
1721556Srgrimes	ip->t.c_iflag &= ~IXANY;
1731556Srgrimes	ip->set = 1;
1741556Srgrimes}
1751556Srgrimes
1761556Srgrimesvoid
17790111Simpf_ek(struct info *ip)
17882237Sdd{
17982237Sdd
18082237Sdd	ip->t.c_cc[VERASE] = CERASE;
18182237Sdd	ip->t.c_cc[VKILL] = CKILL;
18282237Sdd	ip->set = 1;
18382237Sdd}
18482237Sdd
18582237Sddvoid
18690111Simpf_everything(struct info *ip)
1871556Srgrimes{
1881556Srgrimes
18959788Sache	print(&ip->t, &ip->win, ip->ldisc, BSD);
1901556Srgrimes}
1911556Srgrimes
1921556Srgrimesvoid
19390111Simpf_extproc(struct info *ip)
1941556Srgrimes{
1951556Srgrimes
19620424Ssteve	if (ip->off) {
19720424Ssteve		int tmp = 0;
1981556Srgrimes		(void)ioctl(ip->fd, TIOCEXT, &tmp);
1991556Srgrimes	} else {
20020424Ssteve		int tmp = 1;
2011556Srgrimes		(void)ioctl(ip->fd, TIOCEXT, &tmp);
2021556Srgrimes	}
2031556Srgrimes}
2041556Srgrimes
2051556Srgrimesvoid
20690111Simpf_ispeed(struct info *ip)
2071556Srgrimes{
2081556Srgrimes
20976810Skris	cfsetispeed(&ip->t, (speed_t)atoi(ip->arg));
2101556Srgrimes	ip->set = 1;
2111556Srgrimes}
2121556Srgrimes
2131556Srgrimesvoid
21490111Simpf_nl(struct info *ip)
2151556Srgrimes{
2161556Srgrimes
2171556Srgrimes	if (ip->off) {
2181556Srgrimes		ip->t.c_iflag |= ICRNL;
2191556Srgrimes		ip->t.c_oflag |= ONLCR;
2201556Srgrimes	} else {
2211556Srgrimes		ip->t.c_iflag &= ~ICRNL;
2221556Srgrimes		ip->t.c_oflag &= ~ONLCR;
2231556Srgrimes	}
2241556Srgrimes	ip->set = 1;
2251556Srgrimes}
2261556Srgrimes
2271556Srgrimesvoid
22890111Simpf_ospeed(struct info *ip)
2291556Srgrimes{
2301556Srgrimes
23176810Skris	cfsetospeed(&ip->t, (speed_t)atoi(ip->arg));
2321556Srgrimes	ip->set = 1;
2331556Srgrimes}
2341556Srgrimes
2351556Srgrimesvoid
23690111Simpf_raw(struct info *ip)
2371556Srgrimes{
2381556Srgrimes
2391556Srgrimes	if (ip->off)
2401556Srgrimes		f_sane(ip);
2411556Srgrimes	else {
2421556Srgrimes		cfmakeraw(&ip->t);
2431556Srgrimes		ip->t.c_cflag &= ~(CSIZE|PARENB);
2441556Srgrimes		ip->t.c_cflag |= CS8;
2451556Srgrimes		ip->set = 1;
2461556Srgrimes	}
2471556Srgrimes}
2481556Srgrimes
2491556Srgrimesvoid
25090111Simpf_rows(struct info *ip)
2511556Srgrimes{
2521556Srgrimes
2531556Srgrimes	ip->win.ws_row = atoi(ip->arg);
2541556Srgrimes	ip->wset = 1;
2551556Srgrimes}
2561556Srgrimes
2571556Srgrimesvoid
25890111Simpf_sane(struct info *ip)
2591556Srgrimes{
260214680Sed	struct termios def;
2611556Srgrimes
262214680Sed	cfmakesane(&def);
263214680Sed	ip->t.c_cflag = def.c_cflag | (ip->t.c_cflag & CLOCAL);
264214680Sed	ip->t.c_iflag = def.c_iflag;
2651556Srgrimes	/* preserve user-preference flags in lflag */
2661556Srgrimes#define	LKEEP	(ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH)
267214680Sed	ip->t.c_lflag = def.c_lflag | (ip->t.c_lflag & LKEEP);
268214680Sed	ip->t.c_oflag = def.c_oflag;
2691556Srgrimes	ip->set = 1;
2701556Srgrimes}
2711556Srgrimes
2721556Srgrimesvoid
27390111Simpf_size(struct info *ip)
2741556Srgrimes{
2751556Srgrimes
2761556Srgrimes	(void)printf("%d %d\n", ip->win.ws_row, ip->win.ws_col);
2771556Srgrimes}
2781556Srgrimes
2791556Srgrimesvoid
28090111Simpf_speed(struct info *ip)
2811556Srgrimes{
2821556Srgrimes
28337230Sbde	(void)printf("%lu\n", (u_long)cfgetospeed(&ip->t));
2841556Srgrimes}
2851556Srgrimes
2861556Srgrimesvoid
28790111Simpf_tty(struct info *ip)
2881556Srgrimes{
2891556Srgrimes	int tmp;
2901556Srgrimes
2911556Srgrimes	tmp = TTYDISC;
2928148Sache	if (ioctl(ip->fd, TIOCSETD, &tmp) < 0)
2931556Srgrimes		err(1, "TIOCSETD");
2941556Srgrimes}
295