1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <tty.h> 4*219b2ee8SDavid du Colombier 5*219b2ee8SDavid du Colombier typedef struct Mode Mode; 6*219b2ee8SDavid du Colombier struct Mode 7*219b2ee8SDavid du Colombier { 8*219b2ee8SDavid du Colombier char* name; 9*219b2ee8SDavid du Colombier int bit; 10*219b2ee8SDavid du Colombier }; 11*219b2ee8SDavid du Colombier 12*219b2ee8SDavid du Colombier Mode ou[] = 13*219b2ee8SDavid du Colombier { 14*219b2ee8SDavid du Colombier "opost", OPOST, 15*219b2ee8SDavid du Colombier "olcuc", OLCUC, 16*219b2ee8SDavid du Colombier "onlcr", ONLCR, 17*219b2ee8SDavid du Colombier "ocrnl", OCRNL, 18*219b2ee8SDavid du Colombier "onocr", ONOCR, 19*219b2ee8SDavid du Colombier "onlret", ONLRET, 20*219b2ee8SDavid du Colombier "ofill", OFILL, 21*219b2ee8SDavid du Colombier "ofdel", OFDEL, 22*219b2ee8SDavid du Colombier 0 23*219b2ee8SDavid du Colombier }; 24*219b2ee8SDavid du Colombier 25*219b2ee8SDavid du Colombier Mode in[] = 26*219b2ee8SDavid du Colombier { 27*219b2ee8SDavid du Colombier "brkint", BRKINT, 28*219b2ee8SDavid du Colombier "icrnl", ICRNL, 29*219b2ee8SDavid du Colombier "ignbrk", IGNBRK, 30*219b2ee8SDavid du Colombier "igncr", IGNCR, 31*219b2ee8SDavid du Colombier "ignpar", IGNPAR, 32*219b2ee8SDavid du Colombier "inlcr", INLCR, 33*219b2ee8SDavid du Colombier "inpck", INPCK, 34*219b2ee8SDavid du Colombier "istrip", ISTRIP, 35*219b2ee8SDavid du Colombier "ixoff", IXOFF, 36*219b2ee8SDavid du Colombier "ixon", IXON, 37*219b2ee8SDavid du Colombier "parmrk", PARMRK, 38*219b2ee8SDavid du Colombier 0 39*219b2ee8SDavid du Colombier }; 40*219b2ee8SDavid du Colombier 41*219b2ee8SDavid du Colombier Mode lo[] = 42*219b2ee8SDavid du Colombier { 43*219b2ee8SDavid du Colombier "echo", ECHO, 44*219b2ee8SDavid du Colombier "echoe", ECHOE, 45*219b2ee8SDavid du Colombier "echok", ECHOK, 46*219b2ee8SDavid du Colombier "echonl", ECHONL, 47*219b2ee8SDavid du Colombier "icanon", ICANON, 48*219b2ee8SDavid du Colombier "iexten", IEXTEN, 49*219b2ee8SDavid du Colombier "isig", ISIG, 50*219b2ee8SDavid du Colombier "noflsh", NOFLSH, 51*219b2ee8SDavid du Colombier "tostop", TOSTOP, 52*219b2ee8SDavid du Colombier 0 53*219b2ee8SDavid du Colombier }; 54*219b2ee8SDavid du Colombier 55*219b2ee8SDavid du Colombier Mode cc[] = 56*219b2ee8SDavid du Colombier { 57*219b2ee8SDavid du Colombier "eof", VEOF, 58*219b2ee8SDavid du Colombier "eol", VEOL, 59*219b2ee8SDavid du Colombier "erase", VERASE, 60*219b2ee8SDavid du Colombier "intr", VINTR, 61*219b2ee8SDavid du Colombier "kill", VKILL, 62*219b2ee8SDavid du Colombier "min", VMIN, 63*219b2ee8SDavid du Colombier "quit", VQUIT, 64*219b2ee8SDavid du Colombier "susp", VSUSP, 65*219b2ee8SDavid du Colombier "time", VTIME, 66*219b2ee8SDavid du Colombier "start", VSTART, 67*219b2ee8SDavid du Colombier "stop", VSTOP, 68*219b2ee8SDavid du Colombier 0, 69*219b2ee8SDavid du Colombier }; 70*219b2ee8SDavid du Colombier 71*219b2ee8SDavid du Colombier int getmode(int, Termios*); 72*219b2ee8SDavid du Colombier int setmode(int, Termios*); 73*219b2ee8SDavid du Colombier 74*219b2ee8SDavid du Colombier char* 75*219b2ee8SDavid du Colombier ctlchar(char c) 76*219b2ee8SDavid du Colombier { 77*219b2ee8SDavid du Colombier static char buf[10]; 78*219b2ee8SDavid du Colombier 79*219b2ee8SDavid du Colombier if(c == 0x7f) 80*219b2ee8SDavid du Colombier return "DEL"; 81*219b2ee8SDavid du Colombier if(c == 0) 82*219b2ee8SDavid du Colombier return "NUL"; 83*219b2ee8SDavid du Colombier if(c < 32) { 84*219b2ee8SDavid du Colombier buf[0] = '^'; 85*219b2ee8SDavid du Colombier buf[1] = '@'+c; 86*219b2ee8SDavid du Colombier buf[2] = '\0'; 87*219b2ee8SDavid du Colombier return buf; 88*219b2ee8SDavid du Colombier } 89*219b2ee8SDavid du Colombier buf[0] = c; 90*219b2ee8SDavid du Colombier buf[1] = '\0'; 91*219b2ee8SDavid du Colombier return buf; 92*219b2ee8SDavid du Colombier } 93*219b2ee8SDavid du Colombier 94*219b2ee8SDavid du Colombier void 95*219b2ee8SDavid du Colombier showmode(Termios *t) 96*219b2ee8SDavid du Colombier { 97*219b2ee8SDavid du Colombier int i; 98*219b2ee8SDavid du Colombier 99*219b2ee8SDavid du Colombier for(i = 0; cc[i].name; i++) { 100*219b2ee8SDavid du Colombier switch(cc[i].bit) { 101*219b2ee8SDavid du Colombier case VMIN: 102*219b2ee8SDavid du Colombier case VTIME: 103*219b2ee8SDavid du Colombier if(t->cc[i] != 0) 104*219b2ee8SDavid du Colombier print("%s %d ", cc[i].name, t->cc[i]); 105*219b2ee8SDavid du Colombier break; 106*219b2ee8SDavid du Colombier default: 107*219b2ee8SDavid du Colombier print("%s %s ", cc[i].name, ctlchar(t->cc[i])); 108*219b2ee8SDavid du Colombier break; 109*219b2ee8SDavid du Colombier } 110*219b2ee8SDavid du Colombier } 111*219b2ee8SDavid du Colombier print("\n"); 112*219b2ee8SDavid du Colombier 113*219b2ee8SDavid du Colombier for(i = 0; ou[i].name; i++) 114*219b2ee8SDavid du Colombier if(ou[i].bit & t->oflag) 115*219b2ee8SDavid du Colombier print("%s ", ou[i].name); 116*219b2ee8SDavid du Colombier 117*219b2ee8SDavid du Colombier for(i = 0; in[i].name; i++) 118*219b2ee8SDavid du Colombier if(in[i].bit & t->iflag) 119*219b2ee8SDavid du Colombier print("%s ", in[i].name); 120*219b2ee8SDavid du Colombier 121*219b2ee8SDavid du Colombier print("\n"); 122*219b2ee8SDavid du Colombier for(i = 0; lo[i].name; i++) 123*219b2ee8SDavid du Colombier if(lo[i].bit & t->lflag) 124*219b2ee8SDavid du Colombier print("%s ", lo[i].name); 125*219b2ee8SDavid du Colombier print("\n"); 126*219b2ee8SDavid du Colombier } 127*219b2ee8SDavid du Colombier 128*219b2ee8SDavid du Colombier int 129*219b2ee8SDavid du Colombier setreset(char *mode, int *bits, Mode *t) 130*219b2ee8SDavid du Colombier { 131*219b2ee8SDavid du Colombier int i, clr; 132*219b2ee8SDavid du Colombier 133*219b2ee8SDavid du Colombier clr = 0; 134*219b2ee8SDavid du Colombier if(mode[0] == '-') { 135*219b2ee8SDavid du Colombier mode++; 136*219b2ee8SDavid du Colombier clr = 1; 137*219b2ee8SDavid du Colombier } 138*219b2ee8SDavid du Colombier for(i = 0; t[i].name; i++) { 139*219b2ee8SDavid du Colombier if(strcmp(mode, t[i].name) == 0) { 140*219b2ee8SDavid du Colombier if(clr) 141*219b2ee8SDavid du Colombier *bits &= ~t[i].bit; 142*219b2ee8SDavid du Colombier else 143*219b2ee8SDavid du Colombier *bits |= t[i].bit; 144*219b2ee8SDavid du Colombier 145*219b2ee8SDavid du Colombier return 1; 146*219b2ee8SDavid du Colombier } 147*219b2ee8SDavid du Colombier } 148*219b2ee8SDavid du Colombier return 0; 149*219b2ee8SDavid du Colombier } 150*219b2ee8SDavid du Colombier 151*219b2ee8SDavid du Colombier int 152*219b2ee8SDavid du Colombier ccname(char *name) 153*219b2ee8SDavid du Colombier { 154*219b2ee8SDavid du Colombier int i; 155*219b2ee8SDavid du Colombier 156*219b2ee8SDavid du Colombier for(i = 0; cc[i].name; i++) 157*219b2ee8SDavid du Colombier if(strcmp(cc[i].name, name) == 0) 158*219b2ee8SDavid du Colombier return i; 159*219b2ee8SDavid du Colombier 160*219b2ee8SDavid du Colombier return -1; 161*219b2ee8SDavid du Colombier } 162*219b2ee8SDavid du Colombier 163*219b2ee8SDavid du Colombier void 164*219b2ee8SDavid du Colombier main(int argc, char **argv) 165*219b2ee8SDavid du Colombier { 166*219b2ee8SDavid du Colombier Termios t; 167*219b2ee8SDavid du Colombier int i, stdin, wmo, cc; 168*219b2ee8SDavid du Colombier 169*219b2ee8SDavid du Colombier /* Try and get a seek pointer */ 170*219b2ee8SDavid du Colombier stdin = open("/fd/0", ORDWR); 171*219b2ee8SDavid du Colombier if(stdin < 0) 172*219b2ee8SDavid du Colombier stdin = 0; 173*219b2ee8SDavid du Colombier 174*219b2ee8SDavid du Colombier if(getmode(stdin, &t) < 0) { 175*219b2ee8SDavid du Colombier fprint(2, "stty: tiocget %r\n"); 176*219b2ee8SDavid du Colombier exits("1"); 177*219b2ee8SDavid du Colombier } 178*219b2ee8SDavid du Colombier 179*219b2ee8SDavid du Colombier if(argc < 2) { 180*219b2ee8SDavid du Colombier fprint(2, "usage: stty [-a|-g] modes...\n"); 181*219b2ee8SDavid du Colombier exits("1"); 182*219b2ee8SDavid du Colombier } 183*219b2ee8SDavid du Colombier wmo = 0; 184*219b2ee8SDavid du Colombier for(i = 1; i < argc; i++) { 185*219b2ee8SDavid du Colombier if(strcmp(argv[i], "-a") == 0) { 186*219b2ee8SDavid du Colombier showmode(&t); 187*219b2ee8SDavid du Colombier continue; 188*219b2ee8SDavid du Colombier } 189*219b2ee8SDavid du Colombier if(setreset(argv[i], &t.iflag, in)) { 190*219b2ee8SDavid du Colombier wmo++; 191*219b2ee8SDavid du Colombier continue; 192*219b2ee8SDavid du Colombier } 193*219b2ee8SDavid du Colombier if(setreset(argv[i], &t.lflag, lo)) { 194*219b2ee8SDavid du Colombier wmo++; 195*219b2ee8SDavid du Colombier continue; 196*219b2ee8SDavid du Colombier } 197*219b2ee8SDavid du Colombier if(setreset(argv[i], &t.oflag, ou)) { 198*219b2ee8SDavid du Colombier wmo++; 199*219b2ee8SDavid du Colombier continue; 200*219b2ee8SDavid du Colombier } 201*219b2ee8SDavid du Colombier cc = ccname(argv[i]); 202*219b2ee8SDavid du Colombier if(cc != -1 && i+1 < argc) { 203*219b2ee8SDavid du Colombier wmo++; 204*219b2ee8SDavid du Colombier t.cc[cc] = argv[++i][0]; 205*219b2ee8SDavid du Colombier continue; 206*219b2ee8SDavid du Colombier } 207*219b2ee8SDavid du Colombier fprint(2, "stty: bad option/mode %s\n", argv[i]); 208*219b2ee8SDavid du Colombier exits("1"); 209*219b2ee8SDavid du Colombier } 210*219b2ee8SDavid du Colombier 211*219b2ee8SDavid du Colombier if(wmo) { 212*219b2ee8SDavid du Colombier if(setmode(stdin, &t) < 0) { 213*219b2ee8SDavid du Colombier fprint(2, "stty: cant set mode %r\n"); 214*219b2ee8SDavid du Colombier exits("1"); 215*219b2ee8SDavid du Colombier } 216*219b2ee8SDavid du Colombier } 217*219b2ee8SDavid du Colombier 218*219b2ee8SDavid du Colombier exits(0); 219*219b2ee8SDavid du Colombier } 220*219b2ee8SDavid du Colombier 221*219b2ee8SDavid du Colombier int 222*219b2ee8SDavid du Colombier setmode(int fd, Termios *t) 223*219b2ee8SDavid du Colombier { 224*219b2ee8SDavid du Colombier int n, i; 225*219b2ee8SDavid du Colombier char buf[256]; 226*219b2ee8SDavid du Colombier 227*219b2ee8SDavid du Colombier n = sprint(buf, "IOW %4.4lux %4.4lux %4.4lux %4.4lux ", 228*219b2ee8SDavid du Colombier t->iflag, t->oflag, t->cflag, t->lflag); 229*219b2ee8SDavid du Colombier for(i = 0; i < NCCS; i++) 230*219b2ee8SDavid du Colombier n += sprint(buf+n, "%2.2ux ", t->cc[i]); 231*219b2ee8SDavid du Colombier 232*219b2ee8SDavid du Colombier if(seek(fd, -2, 0) != -2) 233*219b2ee8SDavid du Colombier return -1; 234*219b2ee8SDavid du Colombier 235*219b2ee8SDavid du Colombier n = write(fd, buf, n); 236*219b2ee8SDavid du Colombier if(n < 0) 237*219b2ee8SDavid du Colombier return -1; 238*219b2ee8SDavid du Colombier return 0; 239*219b2ee8SDavid du Colombier } 240*219b2ee8SDavid du Colombier 241*219b2ee8SDavid du Colombier /* 242*219b2ee8SDavid du Colombier * Format is: IOR iiii oooo cccc llll xx xx xx xx ... 243*219b2ee8SDavid du Colombier */ 244*219b2ee8SDavid du Colombier int 245*219b2ee8SDavid du Colombier getmode(int fd, Termios *t) 246*219b2ee8SDavid du Colombier { 247*219b2ee8SDavid du Colombier int n; 248*219b2ee8SDavid du Colombier char buf[256]; 249*219b2ee8SDavid du Colombier 250*219b2ee8SDavid du Colombier if(seek(fd, -2, 0) != -2) 251*219b2ee8SDavid du Colombier return -1; 252*219b2ee8SDavid du Colombier 253*219b2ee8SDavid du Colombier n = read(fd, buf, 57); 254*219b2ee8SDavid du Colombier if(n < 0) 255*219b2ee8SDavid du Colombier return -1; 256*219b2ee8SDavid du Colombier 257*219b2ee8SDavid du Colombier t->iflag = strtoul(buf+4, 0, 16); 258*219b2ee8SDavid du Colombier t->oflag = strtoul(buf+9, 0, 16); 259*219b2ee8SDavid du Colombier t->cflag = strtoul(buf+14, 0, 16); 260*219b2ee8SDavid du Colombier t->lflag = strtoul(buf+19, 0, 16); 261*219b2ee8SDavid du Colombier 262*219b2ee8SDavid du Colombier for(n = 0; n < NCCS; n++) 263*219b2ee8SDavid du Colombier t->cc[n] = strtoul(buf+24+(n*3), 0, 16); 264*219b2ee8SDavid du Colombier 265*219b2ee8SDavid du Colombier return 0; 266*219b2ee8SDavid du Colombier } 267