#include <u.h>
#include <libc.h>
#include <tty.h>
typedef struct Mode Mode;
struct Mode
{
char* name;
int bit;
};
Mode ou[] =
{
"opost", OPOST,
"olcuc", OLCUC,
"onlcr", ONLCR,
"ocrnl", OCRNL,
"onocr", ONOCR,
"onlret", ONLRET,
"ofill", OFILL,
"ofdel", OFDEL,
0
};
Mode in[] =
{
"brkint", BRKINT,
"icrnl", ICRNL,
"ignbrk", IGNBRK,
"igncr", IGNCR,
"ignpar", IGNPAR,
"inlcr", INLCR,
"inpck", INPCK,
"istrip", ISTRIP,
"ixoff", IXOFF,
"ixon", IXON,
"parmrk", PARMRK,
0
};
Mode lo[] =
{
"echo", ECHO,
"echoe", ECHOE,
"echok", ECHOK,
"echonl", ECHONL,
"icanon", ICANON,
"iexten", IEXTEN,
"isig", ISIG,
"noflsh", NOFLSH,
"tostop", TOSTOP,
0
};
Mode cc[] =
{
"eof", VEOF,
"eol", VEOL,
"erase", VERASE,
"intr", VINTR,
"kill", VKILL,
"min", VMIN,
"quit", VQUIT,
"susp", VSUSP,
"time", VTIME,
"start", VSTART,
"stop", VSTOP,
0,
};
int getmode(int, Termios*);
int setmode(int, Termios*);
char*
ctlchar(char c)
{
static char buf[10];
if(c == 0x7f)
return "DEL";
if(c == 0)
return "NUL";
if(c < 32) {
buf[0] = '^';
buf[1] = '@'+c;
buf[2] = '\0';
return buf;
}
buf[0] = c;
buf[1] = '\0';
return buf;
}
void
showmode(Termios *t)
{
int i;
for(i = 0; cc[i].name; i++) {
switch(cc[i].bit) {
case VMIN:
case VTIME:
if(t->cc[i] != 0)
print("%s %d ", cc[i].name, t->cc[i]);
break;
default:
print("%s %s ", cc[i].name, ctlchar(t->cc[i]));
break;
}
}
print("\n");
for(i = 0; ou[i].name; i++)
if(ou[i].bit & t->oflag)
print("%s ", ou[i].name);
for(i = 0; in[i].name; i++)
if(in[i].bit & t->iflag)
print("%s ", in[i].name);
print("\n");
for(i = 0; lo[i].name; i++)
if(lo[i].bit & t->lflag)
print("%s ", lo[i].name);
print("\n");
}
int
setreset(char *mode, int *bits, Mode *t)
{
int i, clr;
clr = 0;
if(mode[0] == '-') {
mode++;
clr = 1;
}
for(i = 0; t[i].name; i++) {
if(strcmp(mode, t[i].name) == 0) {
if(clr)
*bits &= ~t[i].bit;
else
*bits |= t[i].bit;
return 1;
}
}
return 0;
}
int
ccname(char *name)
{
int i;
for(i = 0; cc[i].name; i++)
if(strcmp(cc[i].name, name) == 0)
return i;
return -1;
}
void
main(int argc, char **argv)
{
Termios t;
int i, stdin, wmo, cc;
/* Try and get a seek pointer */
stdin = open("/fd/0", ORDWR);
if(stdin < 0)
stdin = 0;
if(getmode(stdin, &t) < 0) {
fprint(2, "stty: tiocget %r\n");
exits("1");
}
if(argc < 2) {
fprint(2, "usage: stty [-a|-g] modes...\n");
exits("1");
}
wmo = 0;
for(i = 1; i < argc; i++) {
if(strcmp(argv[i], "-a") == 0) {
showmode(&t);
continue;
}
if(setreset(argv[i], &t.iflag, in)) {
wmo++;
continue;
}
if(setreset(argv[i], &t.lflag, lo)) {
wmo++;
continue;
}
if(setreset(argv[i], &t.oflag, ou)) {
wmo++;
continue;
}
cc = ccname(argv[i]);
if(cc != -1 && i+1 < argc) {
wmo++;
t.cc[cc] = argv[++i][0];
continue;
}
fprint(2, "stty: bad option/mode %s\n", argv[i]);
exits("1");
}
if(wmo) {
if(setmode(stdin, &t) < 0) {
fprint(2, "stty: cant set mode %r\n");
exits("1");
}
}
exits(0);
}
int
setmode(int fd, Termios *t)
{
int n, i;
char buf[256];
n = sprint(buf, "IOW %4.4ux %4.4ux %4.4ux %4.4ux ",
t->iflag, t->oflag, t->cflag, t->lflag);
for(i = 0; i < NCCS; i++)
n += sprint(buf+n, "%2.2ux ", t->cc[i]);
if(seek(fd, -2, 0) != -2)
return -1;
n = write(fd, buf, n);
if(n < 0)
return -1;
return 0;
}
/*
* Format is: IOR iiii oooo cccc llll xx xx xx xx ...
*/
int
getmode(int fd, Termios *t)
{
int n;
char buf[256];
if(seek(fd, -2, 0) != -2)
return -1;
n = read(fd, buf, 57);
if(n < 0)
return -1;
t->iflag = strtoul(buf+4, 0, 16);
t->oflag = strtoul(buf+9, 0, 16);
t->cflag = strtoul(buf+14, 0, 16);
t->lflag = strtoul(buf+19, 0, 16);
for(n = 0; n < NCCS; n++)
t->cc[n] = strtoul(buf+24+(n*3), 0, 16);
return 0;
}
|