gno/bin/stty/stty.c

303 lines
6.5 KiB
C

/*
* stty.c
*
* Set terminal parameters
*/
#pragma stacksize 1280
#pragma optimize 9
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/ioctl.h>
#include <gno/gno.h>
#include <unistd.h>
typedef struct opts {
char *name;
int item;
} opts_s;
/* B0 - B57600 are defined before these others */
#define LCRTERA_ON 16
#define LCRTERA_OFF 17
#define LCTLECH_ON 18
#define LCTLECH_OFF 19
#define CRMOD_ON 20
#define CRMOD_OFF 21
#define ECHO_ON 22
#define ECHO_OFF 23
#define RAW_ON 24
#define RAW_OFF 25
#define CBREAK_ON 26
#define CBREAK_OFF 27
#define SUSP_C 28
#define STOP_C 29
#define START_C 30
#define QUIT_C 31
#define ERASE_C 32
#define INTR_C 33
#define EOF_C 34
char *baudtbl[] = {
"0",
"50",
"75",
"110",
"134.5",
"150",
"57600",
"300",
"600",
"1200",
"1800",
"2400",
"4800",
"9600",
"19200",
"38400"};
opts_s options[] = {
"75", B75,
"110", B110,
"134", B134,
"150", B150,
"300", B300,
"600", B600,
"1200", B1200,
"1800", B1800,
"2400", B2400,
"4800", B4800,
"9600", B9600,
"19200", B19200,
"38400", B38400,
"57600", B57600,
"lcrtera", LCRTERA_ON,
"-lcrtera", LCRTERA_OFF,
"lctlech", LCTLECH_ON,
"-lctlech", LCTLECH_OFF,
"crmod", CRMOD_ON,
"-crmod", CRMOD_OFF,
"echo", ECHO_ON,
"-echo", ECHO_OFF,
"raw", RAW_ON,
"-raw", RAW_OFF,
"cbreak", CBREAK_ON,
"-cbreak", CBREAK_OFF,
"susp", SUSP_C,
"stop", STOP_C,
"start", START_C,
"quit", QUIT_C,
"erase", ERASE_C,
"intr", INTR_C,
"eof", EOF_C,
"", 0
};
int lookup(char *s)
{
int i;
for (i = 0; options[i].item; i++) {
if (!strcmp(options[i].name,s)) return (options[i].item);
}
return 0;
}
void usage(void)
{
fprintf(stderr,"usage: stty [ option ]...\n"
"\toption: [-]raw,[-]echo,[-]cbreak,[baud]\n"
"\toption c: intr, susp, stop, start, eof, erase\n"
"\t\twhere c is ^X or \\0OCTAL or \\xHEX\n");
exit(1);
}
char parsechar(char *s)
{
int x;
if (s[0] == '^') {
if (strlen(s) != 2) usage();
if (s[1] == '?') return 0x7f;
else return toupper(s[1])-64;
}
else if (s[0] == '\\') {
if (isdigit(s[1]) && (s[0] != 0))
sscanf(s+1,"%d",&x);
else if (toupper(s[1]) == 'X')
sscanf(s+2,"%x",&x);
else if (s[1] == '0')
sscanf(s+1,"%o",&x);
else usage();
printf("char: %d\n",x);
return x;
}
if (strlen(s) != 1) usage();
return s[0];
}
struct sgttyb sg;
struct tchars tc;
struct ltchars ltc;
struct winsize wz;
long localmode;
char *dash[] = {"","-"};
char *doctrl(char c)
{
static char ss[3] = " ";
if (c == 0x7F) {
ss[0] = '^';
ss[1] = '?';
}
else if (c < 32) {
ss[0] = '^';
ss[1] = c + '@';
}
else {
ss[0] = c;
ss[1] = ' ';
}
return ss;
}
void printCurSettings(void)
{
printf("old tty, speed %s baud, %d rows, %d columns\n",
baudtbl[sg.sg_ispeed & 0xF],wz.ws_row,wz.ws_col);
printf("%seven %sodd %sraw %snl %secho %slcase %standem %stabs %scbreak\n",
dash[(sg.sg_flags & EVENP) == 0],
dash[(sg.sg_flags & ODDP) == 0],
dash[(sg.sg_flags & RAW) == 0],
dash[(sg.sg_flags & NLDELAY) == 0],
dash[(sg.sg_flags & ECHO) == 0],
dash[(sg.sg_flags & LCASE) == 0],
dash[(sg.sg_flags & TANDEM) == 0],
dash[(sg.sg_flags & XTABS) == 0],
dash[(sg.sg_flags & CBREAK) == 0]);
printf("%stilde %sflusho %slitout %spass8 %snohang\n",
dash[(localmode & LTILDE) == 0],
dash[(localmode & LFLUSHO) == 0],
dash[(localmode & LLITOUT) == 0],
dash[(localmode & LPASS8) == 0],
dash[(localmode & LNOHANG) == 0]);
printf("%spendin %snoflsh\n",
dash[(localmode & LPENDIN) == 0],
dash[(localmode & LNOFLSH) == 0]);
printf("erase kill werase rprnt flush lnext susp intr quit stop eof\n");
printf("%-7s",doctrl(sg.sg_erase));
printf("%-7s",doctrl(sg.sg_kill));
printf("%-7s",doctrl(ltc.t_werasc));
printf("%-7s",doctrl(ltc.t_rprntc));
printf("%-7s",doctrl(ltc.t_flushc));
printf("%-7s",doctrl(ltc.t_lnextc));
printf("%2s",doctrl(ltc.t_suspc));
printf("/%2s ",doctrl(ltc.t_dsuspc));
printf("%-7s",doctrl(tc.t_intrc));
printf("%-7s",doctrl(tc.t_quitc));
printf("%2s",doctrl(tc.t_stopc));
printf("/%2s ",doctrl(tc.t_startc));
printf("%-7s\n",doctrl(tc.t_eofc));
}
int main(int argc, char *argv[])
{
int i,item;
ioctl(STDIN_FILENO,TIOCGETP,&sg);
ioctl(STDIN_FILENO,TIOCGETC,&tc);
ioctl(STDIN_FILENO,TIOCGLTC,&ltc);
ioctl(STDIN_FILENO,TIOCLGET,&localmode);
ioctl(STDIN_FILENO,TIOCGWINSZ,&wz);
if (argc < 2) {
printCurSettings();
exit(0);
}
for (i = 1; i < argc;) {
switch (item = lookup(argv[i])) {
case INTR_C:
tc.t_intrc = parsechar(argv[i+1]);
i++;
break;
case SUSP_C:
ltc.t_suspc = parsechar(argv[i+1]);
i++;
break;
case STOP_C:
tc.t_stopc = parsechar(argv[i+1]);
i++;
break;
case START_C:
tc.t_startc = parsechar(argv[i+1]);
i++;
break;
case QUIT_C:
tc.t_quitc = parsechar(argv[i+1]);
i++;
break;
case ERASE_C:
sg.sg_erase = parsechar(argv[i+1]);
i++;
break;
case EOF_C:
tc.t_eofc = parsechar(argv[i+1]);
i++;
break;
case ECHO_ON:
sg.sg_flags |= ECHO;
break;
case ECHO_OFF:
sg.sg_flags &= ~ECHO;
break;
case RAW_OFF:
sg.sg_flags &= ~RAW;
break;
case RAW_ON:
sg.sg_flags |= RAW;
break;
case CBREAK_OFF:
sg.sg_flags &= ~CBREAK;
break;
case CBREAK_ON:
sg.sg_flags |= CBREAK;
break;
case CRMOD_OFF:
sg.sg_flags &= ~CRMOD;
break;
case CRMOD_ON:
sg.sg_flags |= CRMOD;
break;
case LCTLECH_ON:
localmode |= LCTLECH;
break;
case LCTLECH_OFF:
localmode &= ~LCTLECH;
break;
case LCRTERA_ON:
localmode |= LCRTERA;
break;
case LCRTERA_OFF:
localmode &= ~LCRTERA;
break;
default:
if ((item != 0) && (item <= B38400)) {
sg.sg_ispeed = item;
sg.sg_ospeed = item;
} else usage();
break;
}
i++;
}
ioctl(STDIN_FILENO,TIOCSETP,&sg);
ioctl(STDIN_FILENO,TIOCSETC,&tc);
ioctl(STDIN_FILENO,TIOCSLTC,&ltc);
ioctl(STDIN_FILENO,TIOCLSET,&localmode);
}