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