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