1 /*- 2 * Copyright (c) 1989, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1989, 1991 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)stty.c 5.21 (Berkeley) 05/02/91"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/ioctl.h> 20 #include <termios.h> 21 #include <fcntl.h> 22 #include <errno.h> 23 #include <unistd.h> 24 #include <stdio.h> 25 #include <ctype.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include "stty.h" 29 #include "extern.h" 30 31 static void usage __P((void)); 32 33 main(argc, argv) 34 int argc; 35 char **argv; 36 { 37 extern char *optarg; 38 extern int optind; 39 extern struct cchar cchars1[], cchars2[]; 40 extern struct modes cmodes[], imodes[], lmodes[], omodes[]; 41 register struct modes *mp; 42 register struct cchar *cp; 43 struct winsize win; 44 struct termios t; 45 enum FMT fmt; 46 int ch, ctl, ldisc, tmp; 47 48 ctl = STDIN_FILENO; 49 fmt = NOTSET; 50 while ((ch = getopt(argc, argv, "aef:g")) != EOF) 51 switch(ch) { 52 case 'a': /* undocumented: POSIX compatibility */ 53 fmt = POSIX; 54 break; 55 case 'e': 56 fmt = BSD; 57 break; 58 case 'f': 59 if ((ctl = open(optarg, O_RDONLY | O_NONBLOCK)) < 0) 60 err(optarg); 61 break; 62 case 'g': 63 fmt = GFLAG; 64 break; 65 case '?': 66 usage(); 67 default: 68 --optind; 69 goto args; 70 } 71 72 args: argc -= optind; 73 argv += optind; 74 75 if (ioctl(ctl, TIOCGETD, &ldisc) < 0) 76 err("TIOCGETD: %s", strerror(errno)); 77 if (tcgetattr(ctl, &t) < 0) 78 err("tcgetattr: %s", strerror(errno)); 79 if (ioctl(ctl, TIOCGWINSZ, &win) < 0) 80 warn("TIOCGWINSZ: %s\n", strerror(errno)); 81 82 checkredirect(); /* conversion aid */ 83 84 switch(fmt) { 85 case NOTSET: 86 if (*argv) 87 break; 88 /* FALLTHROUGH */ 89 case BSD: 90 case POSIX: 91 print(&t, &win, ldisc, fmt); 92 break; 93 case GFLAG: 94 gprint(&t, &win, ldisc); 95 break; 96 } 97 98 #define CHK(s) (**argv == s[0] && !strcmp(*argv, s)) 99 100 for (; *argv; ++argv) { 101 if (CHK("-nl")) { 102 t.c_iflag |= ICRNL; 103 t.c_oflag |= ONLCR; 104 continue; 105 } 106 if (CHK("all")) { 107 print(&t, &win, ldisc, BSD); 108 continue; 109 } 110 if (CHK("-cbreak")) 111 goto reset; 112 if (CHK("cbreak")) { 113 t.c_iflag | BRKINT|IXON|IMAXBEL; 114 t.c_oflag |= OPOST; 115 t.c_lflag |= ISIG|IEXTEN; 116 t.c_lflag &= ~ICANON; 117 continue; 118 } 119 if (CHK("cols")) { 120 if (!*++argv) 121 err("option requires an argument -- cols"); 122 goto columns; 123 } 124 if (CHK("columns")) { 125 if (!*++argv) 126 err("option requires an argument -- columns"); 127 columns: win.ws_col = atoi(*argv); 128 continue; 129 } 130 if (CHK("cooked")) 131 goto reset; 132 if (CHK("dec")) { 133 t.c_cc[VERASE] = (u_char)0177; 134 t.c_cc[VKILL] = CTRL('u'); 135 t.c_cc[VINTR] = CTRL('c'); 136 t.c_lflag &= ~ECHOPRT; 137 t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; 138 t.c_iflag &= ~IXANY; 139 continue; 140 } 141 if (CHK("everything")) { 142 print(&t, &win, ldisc, BSD); 143 continue; 144 } 145 if (CHK("-extproc")) { 146 tmp = 0; 147 ioctl(ctl, TIOCEXT, &tmp); 148 continue; 149 } 150 if (CHK("extrpc")) { 151 tmp = 1; 152 ioctl(ctl, TIOCEXT, &tmp); 153 continue; 154 } 155 if (CHK("ispeed")) { 156 if (!*++argv) 157 err("option requires an argument -- ispeed"); 158 cfsetispeed(&t, atoi(*argv)); 159 continue; 160 } 161 if (CHK("new")) 162 goto tty; 163 if (CHK("nl")) { 164 t.c_iflag &= ~ICRNL; 165 t.c_oflag &= ~ONLCR; 166 continue; 167 } 168 if (CHK("old")) 169 goto tty; 170 if (CHK("ospeed")) { 171 if (!*++argv) 172 err("option requires an argument -- ospeed"); 173 cfsetospeed(&t, atoi(*argv)); 174 continue; 175 } 176 if (CHK("-raw")) 177 goto reset; 178 if (CHK("raw")) { 179 cfmakeraw(&t); 180 t.c_cflag &= ~(CSIZE|PARENB); 181 t.c_cflag |= CS8; 182 continue; 183 } 184 if (CHK("rows")) { 185 if (!*++argv) 186 err("option requires an argument -- rows"); 187 win.ws_row = atoi(*argv); 188 continue; 189 } 190 if (CHK("sane")) { 191 reset: t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL); 192 t.c_iflag = TTYDEF_IFLAG; 193 t.c_iflag |= ICRNL; 194 /* preserve user-preference flags in lflag */ 195 #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) 196 t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP); 197 t.c_oflag = TTYDEF_OFLAG; 198 continue; 199 } 200 if (CHK("size")) { 201 (void)printf("%d %d\n", win.ws_row, win.ws_col); 202 continue; 203 } 204 if (CHK("speed")) { 205 (void)printf("%d\n", cfgetospeed(&t)); 206 continue; 207 } 208 if (CHK("tty")) { 209 tty: tmp = TTYDISC; 210 if (ioctl(0, TIOCSETD, &tmp) < 0) 211 err("TIOCSETD: %s", strerror(errno)); 212 continue; 213 } 214 215 for (mp = cmodes; mp->name; ++mp) 216 if (CHK(mp->name)) { 217 t.c_cflag &= ~mp->unset; 218 t.c_cflag |= mp->set; 219 goto next; 220 } 221 for (mp = imodes; mp->name; ++mp) 222 if (CHK(mp->name)) { 223 t.c_iflag &= ~mp->unset; 224 t.c_iflag |= mp->set; 225 goto next; 226 } 227 for (mp = lmodes; mp->name; ++mp) 228 if (CHK(mp->name)) { 229 t.c_lflag &= ~mp->unset; 230 t.c_lflag |= mp->set; 231 goto next; 232 } 233 for (mp = omodes; mp->name; ++mp) 234 if (CHK(mp->name)) { 235 t.c_oflag &= ~mp->unset; 236 t.c_oflag |= mp->set; 237 goto next; 238 } 239 for (cp = cchars1; cp->name; ++cp) { 240 if (!CHK(cp->name)) 241 continue; 242 goto ccfound; 243 } 244 for (cp = cchars2; cp->name; ++cp) { 245 if (!CHK(cp->name)) 246 continue; 247 ccfound: if (!*++argv) 248 err("option requires an argument -- %s", 249 cp->name); 250 if (CHK("undef") || CHK("disable")) 251 t.c_cc[cp->sub] = _POSIX_VDISABLE; 252 else if (**argv == '^') 253 t.c_cc[cp->sub] = 254 ((*argv)[1] == '?') ? 0177 : 255 ((*argv)[1] == '-') ? _POSIX_VDISABLE : 256 (*argv)[1] & 037; 257 else 258 t.c_cc[cp->sub] = **argv; 259 goto next; 260 } 261 262 if (isdigit(**argv)) { 263 cfsetospeed(&t, atoi(*argv)); 264 cfsetispeed(&t, atoi(*argv)); 265 goto next; 266 } 267 if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) { 268 gread(&t, *argv + sizeof("gfmt1") - 1); 269 goto next; 270 } 271 272 err("illegal option -- %s", *argv); 273 next: continue; 274 } 275 276 if (tcsetattr(ctl, 0, &t) < 0) 277 err("tcsetattr: %s", strerror(errno)); 278 if (ioctl(ctl, TIOCSWINSZ, &win) < 0) 279 warn("TIOCSWINSZ: %s", strerror(errno)); 280 exit(0); 281 } 282 283 static void 284 usage() 285 { 286 (void)fprintf(stderr, "usage: stty: [-eg] [-f file] [options]\n"); 287 exit(1); 288 } 289