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