1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 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/types.h> 33 34 #include <err.h> 35 #include <stdlib.h> 36 #include <stdio.h> 37 #include <string.h> 38 39 #include "stty.h" 40 #include "extern.h" 41 42 __BEGIN_DECLS 43 static int c_key(const void *, const void *); 44 void f_all(struct info *); 45 void f_cbreak(struct info *); 46 void f_columns(struct info *); 47 void f_dec(struct info *); 48 void f_ek(struct info *); 49 void f_everything(struct info *); 50 void f_extproc(struct info *); 51 void f_ispeed(struct info *); 52 void f_nl(struct info *); 53 void f_ospeed(struct info *); 54 void f_raw(struct info *); 55 void f_rows(struct info *); 56 void f_sane(struct info *); 57 void f_size(struct info *); 58 void f_speed(struct info *); 59 void f_tty(struct info *); 60 __END_DECLS 61 62 static struct key { 63 const char *name; /* name */ 64 void (*f)(struct info *); /* function */ 65 #define F_NEEDARG 0x01 /* needs an argument */ 66 #define F_OFFOK 0x02 /* can turn off */ 67 int flags; 68 } keys[] = { 69 { "all", f_all, 0 }, 70 { "cbreak", f_cbreak, F_OFFOK }, 71 { "cols", f_columns, F_NEEDARG }, 72 { "columns", f_columns, F_NEEDARG }, 73 { "cooked", f_sane, 0 }, 74 { "dec", f_dec, 0 }, 75 { "ek", f_ek, 0 }, 76 { "everything", f_everything, 0 }, 77 { "extproc", f_extproc, F_OFFOK }, 78 { "ispeed", f_ispeed, F_NEEDARG }, 79 { "new", f_tty, 0 }, 80 { "nl", f_nl, F_OFFOK }, 81 { "old", f_tty, 0 }, 82 { "ospeed", f_ospeed, F_NEEDARG }, 83 { "raw", f_raw, F_OFFOK }, 84 { "rows", f_rows, F_NEEDARG }, 85 { "sane", f_sane, 0 }, 86 { "size", f_size, 0 }, 87 { "speed", f_speed, 0 }, 88 { "tty", f_tty, 0 }, 89 }; 90 91 static int 92 c_key(const void *a, const void *b) 93 { 94 95 return (strcmp(((const struct key *)a)->name, ((const struct key *)b)->name)); 96 } 97 98 int 99 ksearch(char ***argvp, struct info *ip) 100 { 101 char *name; 102 struct key *kp, tmp; 103 104 name = **argvp; 105 if (*name == '-') { 106 ip->off = 1; 107 ++name; 108 } else 109 ip->off = 0; 110 111 tmp.name = name; 112 if (!(kp = (struct key *)bsearch(&tmp, keys, 113 sizeof(keys)/sizeof(struct key), sizeof(struct key), c_key))) 114 return (0); 115 if (!(kp->flags & F_OFFOK) && ip->off) { 116 warnx("illegal option -- -%s", name); 117 usage(); 118 } 119 if (kp->flags & F_NEEDARG && !(ip->arg = *++*argvp)) { 120 warnx("option requires an argument -- %s", name); 121 usage(); 122 } 123 kp->f(ip); 124 return (1); 125 } 126 127 void 128 f_all(struct info *ip) 129 { 130 print(&ip->t, &ip->win, ip->ldisc, BSD); 131 } 132 133 void 134 f_cbreak(struct info *ip) 135 { 136 137 if (ip->off) 138 f_sane(ip); 139 else { 140 ip->t.c_iflag |= BRKINT|IXON|IMAXBEL; 141 ip->t.c_oflag |= OPOST; 142 ip->t.c_lflag |= ISIG|IEXTEN; 143 ip->t.c_lflag &= ~ICANON; 144 ip->set = 1; 145 } 146 } 147 148 void 149 f_columns(struct info *ip) 150 { 151 152 ip->win.ws_col = atoi(ip->arg); 153 ip->wset = 1; 154 } 155 156 void 157 f_dec(struct info *ip) 158 { 159 160 ip->t.c_cc[VERASE] = (u_char)0177; 161 ip->t.c_cc[VKILL] = CTRL('u'); 162 ip->t.c_cc[VINTR] = CTRL('c'); 163 ip->t.c_lflag &= ~ECHOPRT; 164 ip->t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; 165 ip->t.c_iflag &= ~IXANY; 166 ip->set = 1; 167 } 168 169 void 170 f_ek(struct info *ip) 171 { 172 173 ip->t.c_cc[VERASE] = CERASE; 174 ip->t.c_cc[VKILL] = CKILL; 175 ip->set = 1; 176 } 177 178 void 179 f_everything(struct info *ip) 180 { 181 182 print(&ip->t, &ip->win, ip->ldisc, BSD); 183 } 184 185 void 186 f_extproc(struct info *ip) 187 { 188 189 if (ip->off) { 190 int tmp = 0; 191 (void)ioctl(ip->fd, TIOCEXT, &tmp); 192 } else { 193 int tmp = 1; 194 (void)ioctl(ip->fd, TIOCEXT, &tmp); 195 } 196 } 197 198 void 199 f_ispeed(struct info *ip) 200 { 201 202 cfsetispeed(&ip->t, (speed_t)atoi(ip->arg)); 203 ip->set = 1; 204 } 205 206 void 207 f_nl(struct info *ip) 208 { 209 210 if (ip->off) { 211 ip->t.c_iflag |= ICRNL; 212 ip->t.c_oflag |= ONLCR; 213 } else { 214 ip->t.c_iflag &= ~ICRNL; 215 ip->t.c_oflag &= ~ONLCR; 216 } 217 ip->set = 1; 218 } 219 220 void 221 f_ospeed(struct info *ip) 222 { 223 224 cfsetospeed(&ip->t, (speed_t)atoi(ip->arg)); 225 ip->set = 1; 226 } 227 228 void 229 f_raw(struct info *ip) 230 { 231 232 if (ip->off) 233 f_sane(ip); 234 else { 235 cfmakeraw(&ip->t); 236 ip->t.c_cflag &= ~(CSIZE|PARENB); 237 ip->t.c_cflag |= CS8; 238 ip->set = 1; 239 } 240 } 241 242 void 243 f_rows(struct info *ip) 244 { 245 246 ip->win.ws_row = atoi(ip->arg); 247 ip->wset = 1; 248 } 249 250 void 251 f_sane(struct info *ip) 252 { 253 struct termios def; 254 255 cfmakesane(&def); 256 ip->t.c_cflag = def.c_cflag | (ip->t.c_cflag & CLOCAL); 257 ip->t.c_iflag = def.c_iflag; 258 /* preserve user-preference flags in lflag */ 259 #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) 260 ip->t.c_lflag = def.c_lflag | (ip->t.c_lflag & LKEEP); 261 ip->t.c_oflag = def.c_oflag; 262 ip->set = 1; 263 } 264 265 void 266 f_size(struct info *ip) 267 { 268 269 (void)printf("%d %d\n", ip->win.ws_row, ip->win.ws_col); 270 } 271 272 void 273 f_speed(struct info *ip) 274 { 275 276 (void)printf("%lu\n", (u_long)cfgetospeed(&ip->t)); 277 } 278 279 void 280 f_tty(struct info *ip) 281 { 282 int tmp; 283 284 tmp = TTYDISC; 285 if (ioctl(ip->fd, TIOCSETD, &tmp) < 0) 286 err(1, "TIOCSETD"); 287 } 288