key.c revision 37230
1/*-
2 * Copyright (c) 1991, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static char sccsid[] = "@(#)key.c	8.3 (Berkeley) 4/2/94";
37#else
38static const char rcsid[] =
39	"$Id: key.c,v 1.9 1997/08/24 00:26:12 steve Exp $";
40#endif
41#endif /* not lint */
42
43#include <sys/types.h>
44
45#include <err.h>
46#include <errno.h>
47#include <stdlib.h>
48#include <stdio.h>
49#include <string.h>
50
51#include "stty.h"
52#include "extern.h"
53
54__BEGIN_DECLS
55void	f_all __P((struct info *));
56void	f_cbreak __P((struct info *));
57void	f_columns __P((struct info *));
58void	f_dec __P((struct info *));
59void	f_everything __P((struct info *));
60void	f_extproc __P((struct info *));
61void	f_ispeed __P((struct info *));
62void	f_nl __P((struct info *));
63void	f_ospeed __P((struct info *));
64void	f_raw __P((struct info *));
65void	f_rows __P((struct info *));
66void	f_sane __P((struct info *));
67void	f_size __P((struct info *));
68void	f_speed __P((struct info *));
69void	f_tty __P((struct info *));
70__END_DECLS
71
72static struct key {
73	char *name;				/* name */
74	void (*f) __P((struct info *));		/* function */
75#define	F_NEEDARG	0x01			/* needs an argument */
76#define	F_OFFOK		0x02			/* can turn off */
77	int flags;
78} keys[] = {
79	{ "all",	f_all,		0 },
80	{ "cbreak",	f_cbreak,	F_OFFOK },
81	{ "cols",	f_columns,	F_NEEDARG },
82	{ "columns",	f_columns,	F_NEEDARG },
83	{ "cooked", 	f_sane,		0 },
84	{ "dec",	f_dec,		0 },
85	{ "everything",	f_everything,	0 },
86	{ "extproc",	f_extproc,	F_OFFOK },
87	{ "ispeed",	f_ispeed,	F_NEEDARG },
88	{ "new",	f_tty,		0 },
89	{ "nl",		f_nl,		F_OFFOK },
90	{ "old",	f_tty,		0 },
91	{ "ospeed",	f_ospeed,	F_NEEDARG },
92	{ "raw",	f_raw,		F_OFFOK },
93	{ "rows",	f_rows,		F_NEEDARG },
94	{ "sane",	f_sane,		0 },
95	{ "size",	f_size,		0 },
96	{ "speed",	f_speed,	0 },
97	{ "tty",	f_tty,		0 },
98};
99
100static int
101c_key(a, b)
102        const void *a, *b;
103{
104
105        return (strcmp(((struct key *)a)->name, ((struct key *)b)->name));
106}
107
108int
109ksearch(argvp, ip)
110	char ***argvp;
111	struct info *ip;
112{
113	char *name;
114	struct key *kp, tmp;
115
116	name = **argvp;
117	if (*name == '-') {
118		ip->off = 1;
119		++name;
120	} else
121		ip->off = 0;
122
123	tmp.name = name;
124	if (!(kp = (struct key *)bsearch(&tmp, keys,
125	    sizeof(keys)/sizeof(struct key), sizeof(struct key), c_key)))
126		return (0);
127	if (!(kp->flags & F_OFFOK) && ip->off) {
128		warnx("illegal option -- -%s", name);
129		usage();
130	}
131	if (kp->flags & F_NEEDARG && !(ip->arg = *++*argvp)) {
132		warnx("option requires an argument -- %s", name);
133		usage();
134	}
135	kp->f(ip);
136	return (1);
137}
138
139void
140f_all(ip)
141	struct info *ip;
142{
143	print(&ip->t, &ip->win, ip->ldisc, BSD);
144}
145
146void
147f_cbreak(ip)
148	struct info *ip;
149{
150
151	if (ip->off)
152		f_sane(ip);
153	else {
154		ip->t.c_iflag |= BRKINT|IXON|IMAXBEL;
155		ip->t.c_oflag |= OPOST;
156		ip->t.c_lflag |= ISIG|IEXTEN;
157		ip->t.c_lflag &= ~ICANON;
158		ip->set = 1;
159	}
160}
161
162void
163f_columns(ip)
164	struct info *ip;
165{
166
167	ip->win.ws_col = atoi(ip->arg);
168	ip->wset = 1;
169}
170
171void
172f_dec(ip)
173	struct info *ip;
174{
175
176	ip->t.c_cc[VERASE] = (u_char)0177;
177	ip->t.c_cc[VKILL] = CTRL('u');
178	ip->t.c_cc[VINTR] = CTRL('c');
179	ip->t.c_lflag &= ~ECHOPRT;
180	ip->t.c_lflag |= ECHOE|ECHOKE|ECHOCTL;
181	ip->t.c_iflag &= ~IXANY;
182	ip->set = 1;
183}
184
185void
186f_everything(ip)
187	struct info *ip;
188{
189
190	print(&ip->t, &ip->win, ip->ldisc, BSD);
191}
192
193void
194f_extproc(ip)
195	struct info *ip;
196{
197
198	if (ip->off) {
199		int tmp = 0;
200		(void)ioctl(ip->fd, TIOCEXT, &tmp);
201	} else {
202		int tmp = 1;
203		(void)ioctl(ip->fd, TIOCEXT, &tmp);
204	}
205}
206
207void
208f_ispeed(ip)
209	struct info *ip;
210{
211
212	cfsetispeed(&ip->t, atoi(ip->arg));
213	ip->set = 1;
214}
215
216void
217f_nl(ip)
218	struct info *ip;
219{
220
221	if (ip->off) {
222		ip->t.c_iflag |= ICRNL;
223		ip->t.c_oflag |= ONLCR;
224	} else {
225		ip->t.c_iflag &= ~ICRNL;
226		ip->t.c_oflag &= ~ONLCR;
227	}
228	ip->set = 1;
229}
230
231void
232f_ospeed(ip)
233	struct info *ip;
234{
235
236	cfsetospeed(&ip->t, atoi(ip->arg));
237	ip->set = 1;
238}
239
240void
241f_raw(ip)
242	struct info *ip;
243{
244
245	if (ip->off)
246		f_sane(ip);
247	else {
248		cfmakeraw(&ip->t);
249		ip->t.c_cflag &= ~(CSIZE|PARENB);
250		ip->t.c_cflag |= CS8;
251		ip->set = 1;
252	}
253}
254
255void
256f_rows(ip)
257	struct info *ip;
258{
259
260	ip->win.ws_row = atoi(ip->arg);
261	ip->wset = 1;
262}
263
264void
265f_sane(ip)
266	struct info *ip;
267{
268
269	ip->t.c_cflag = TTYDEF_CFLAG | (ip->t.c_cflag & CLOCAL);
270	ip->t.c_iflag = TTYDEF_IFLAG;
271	ip->t.c_iflag |= ICRNL;
272	/* preserve user-preference flags in lflag */
273#define	LKEEP	(ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH)
274	ip->t.c_lflag = TTYDEF_LFLAG | (ip->t.c_lflag & LKEEP);
275	ip->t.c_oflag = TTYDEF_OFLAG;
276	ip->set = 1;
277}
278
279void
280f_size(ip)
281	struct info *ip;
282{
283
284	(void)printf("%d %d\n", ip->win.ws_row, ip->win.ws_col);
285}
286
287void
288f_speed(ip)
289	struct info *ip;
290{
291
292	(void)printf("%lu\n", (u_long)cfgetospeed(&ip->t));
293}
294
295void
296f_tty(ip)
297	struct info *ip;
298{
299	int tmp;
300
301	tmp = TTYDISC;
302	if (ioctl(ip->fd, TIOCSETD, &tmp) < 0)
303		err(1, "TIOCSETD");
304}
305