stty.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018 K. Lange
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <ctype.h>
  11. #include <termios.h>
  12. #include <sys/ioctl.h>
  13. static int hide_defaults = 1;
  14. static int printed = 0;
  15. static void print_cc(struct termios * t, const char * lbl, int val, int def) {
  16. int c = t->c_cc[val];
  17. if (hide_defaults && c == def) return;
  18. if (!c) {
  19. fprintf(stdout, "%s = <undef>; ", lbl);
  20. } else if (c < 32) {
  21. fprintf(stdout, "%s = ^%c; ", lbl, '@' + c);
  22. } else if (c == 0x7F) {
  23. fprintf(stdout, "%s = ^?; ", lbl);
  24. } else {
  25. fprintf(stdout, "%s = %c; ", lbl, c);
  26. }
  27. printed = 1;
  28. }
  29. static void print_(int flags, const char * lbl, int val, int def) {
  30. int c = !!(flags & val);
  31. if (!hide_defaults || c != def) {
  32. fprintf(stdout, "%s%s ", c ? "" : "-", lbl);
  33. printed = 1;
  34. }
  35. }
  36. #define print_cflag(lbl,val,def) print_(t.c_cflag, lbl, val, def)
  37. #define print_iflag(lbl,val,def) print_(t.c_iflag, lbl, val, def)
  38. #define print_oflag(lbl,val,def) print_(t.c_oflag, lbl, val, def)
  39. #define print_lflag(lbl,val,def) print_(t.c_lflag, lbl, val, def)
  40. static int set_char_(struct termios *t, const char * lbl, int val, const char * cmp, const char * arg, int * i) {
  41. if (!strcmp(cmp, lbl)) {
  42. if (!arg) {
  43. fprintf(stderr, "%s: expected argument\n", lbl);
  44. exit(1);
  45. }
  46. /* Parse arg */
  47. if (strlen(arg) == 1) {
  48. /* Assume raw character */
  49. t->c_cc[val] = *arg;
  50. } else if (*arg == '^') { /* ^c, etc. */
  51. int v = toupper(arg[1]);
  52. if (v == '?') { /* special case */
  53. t->c_cc[val] = 0x7F;
  54. } else {
  55. t->c_cc[val] = v - '@';
  56. }
  57. } else {
  58. /* Assume decimal for now */
  59. int v = atoi(arg);
  60. t->c_cc[val] = v;
  61. }
  62. (*i)++;
  63. return 1;
  64. }
  65. return 0;
  66. }
  67. #define set_char(lbl,val) if (set_char_(&t, lbl, val, argv[i], argv[i+1], &i)) { i += 2; continue; }
  68. static int setunset_flag(tcflag_t * flag, const char * lbl, int val, const char * cmp) {
  69. if (*cmp == '-') {
  70. if (!strcmp(cmp+1, lbl)) {
  71. (*flag) = (*flag) & (~val);
  72. return 1;
  73. }
  74. } else {
  75. if (!strcmp(cmp, lbl)) {
  76. (*flag) = (*flag) | (val);
  77. return 1;
  78. }
  79. }
  80. return 0;
  81. }
  82. #define set_cflag(lbl,val) if (setunset_flag(&(t.c_cflag), lbl, val, argv[i])) { i++; continue; }
  83. #define set_iflag(lbl,val) if (setunset_flag(&(t.c_iflag), lbl, val, argv[i])) { i++; continue; }
  84. #define set_oflag(lbl,val) if (setunset_flag(&(t.c_oflag), lbl, val, argv[i])) { i++; continue; }
  85. #define set_lflag(lbl,val) if (setunset_flag(&(t.c_lflag), lbl, val, argv[i])) { i++; continue; }
  86. static int set_toggle_(tcflag_t * flag, const char * lbl, int base, int val, const char * cmp) {
  87. if (!strcmp(cmp, lbl)) {
  88. (*flag) = (*flag) & ~(base);
  89. (*flag) = (*flag) | (val);
  90. return 1;
  91. }
  92. return 0;
  93. }
  94. #define set_ctoggle(lbl,base,val) if (set_toggle_(&(t.c_cflag), lbl, base, val, argv[i])) { i++; continue; }
  95. #define set_otoggle(lbl,base,val) if (set_toggle_(&(t.c_oflag), lbl, base, val, argv[i])) { i++; continue; }
  96. static int show_settings(int all) {
  97. /* Size */
  98. struct winsize w;
  99. ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
  100. fprintf(stdout, "rows %d; columns %d; ypixels %d; xpixels %d;\n", w.ws_row, w.ws_col, w.ws_ypixel, w.ws_xpixel);
  101. printed = 0;
  102. struct termios t;
  103. tcgetattr(STDERR_FILENO, &t);
  104. /* Keys */
  105. print_cc(&t, "intr", VINTR, 3);
  106. print_cc(&t, "quit", VQUIT, 28);
  107. print_cc(&t, "erase", VERASE, 0x7F);
  108. print_cc(&t, "kill", VKILL, 21);
  109. print_cc(&t, "eof", VEOF, 4);
  110. print_cc(&t, "eol", VEOL, 0);
  111. if (printed) { fprintf(stdout, "\n"); printed = 0; }
  112. print_cc(&t, "start", VSTART, 17);
  113. print_cc(&t, "stop", VSTOP, 19);
  114. print_cc(&t, "susp", VSUSP, 26);
  115. print_cc(&t, "lnext", VLNEXT, 22);
  116. print_cc(&t, "werase",VWERASE, 23);
  117. /* MIN, TIME */
  118. if (!hide_defaults || t.c_cc[VMIN] != 1) { fprintf(stdout, "min = %d; ", t.c_cc[VMIN]); printed = 1; }
  119. if (!hide_defaults || t.c_cc[VTIME] != 0) { fprintf(stdout, "time = %d; ", t.c_cc[VTIME]); printed = 1; }
  120. if (printed) { fprintf(stdout, "\n"); printed = 0; }
  121. switch ((t.c_cflag & CSIZE)) {
  122. case CS5: fprintf(stdout, "cs5 "); printed = 1; break;
  123. case CS6: fprintf(stdout, "cs6 "); printed = 1; break;
  124. case CS7: fprintf(stdout, "cs7 "); printed = 1; break;
  125. case CS8: if (!hide_defaults) { fprintf(stdout, "cs8 "); printed = 1; } break;
  126. }
  127. print_cflag("cstopb", CSTOPB, 0);
  128. print_cflag("cread", CREAD, 1);
  129. print_cflag("parenb", PARENB, 0);
  130. print_cflag("parodd", PARODD, 0);
  131. print_cflag("hupcl", HUPCL, 0);
  132. print_cflag("clocal", CLOCAL, 0);
  133. if (printed) { fprintf(stdout, "\n"); printed = 0; }
  134. print_iflag("brkint", BRKINT, 1);
  135. print_iflag("icrnl", ICRNL, 1);
  136. print_iflag("ignbrk", IGNBRK, 0);
  137. print_iflag("igncr", IGNCR, 0);
  138. print_iflag("ignpar", IGNPAR, 0);
  139. print_iflag("inlcr", INLCR, 0);
  140. print_iflag("inpck", INPCK, 0);
  141. print_iflag("istrip", ISTRIP, 0);
  142. print_iflag("ixany", IXANY, 0);
  143. print_iflag("ixoff", IXOFF, 0);
  144. print_iflag("ixon", IXON, 0);
  145. print_iflag("parmrk", PARMRK, 0);
  146. if (printed) { fprintf(stdout, "\n"); printed = 0; }
  147. print_oflag("opost", OPOST, 1);
  148. print_oflag("olcuc", OLCUC, 0);
  149. print_oflag("onlcr", ONLCR, 1);
  150. print_oflag("ocrnl", OCRNL, 0);
  151. print_oflag("onocr", ONOCR, 0);
  152. print_oflag("onlret", ONLRET, 0);
  153. print_oflag("ofill", OFILL, 0);
  154. print_oflag("ofdel", OFDEL, 0);
  155. switch ((t.c_oflag & CRDLY)) {
  156. case CR0: if (!hide_defaults) { fprintf(stdout, "cr0 "); printed = 1; } break;
  157. case CR1: fprintf(stdout, "cr1 "); printed = 1; break;
  158. case CR2: fprintf(stdout, "cr2 "); printed = 1; break;
  159. case CR3: fprintf(stdout, "cr3 "); printed = 1; break;
  160. }
  161. switch ((t.c_oflag & NLDLY)) {
  162. case NL0: if (!hide_defaults) { fprintf(stdout, "nl0 "); printed = 1; } break;
  163. case NL1: fprintf(stdout, "nl1 "); printed = 1; break;
  164. }
  165. switch ((t.c_oflag & TABDLY)) {
  166. case TAB0: if (!hide_defaults) { fprintf(stdout, "tab0 "); printed = 1; } break;
  167. case TAB1: fprintf(stdout, "tab1 "); printed = 1; break;
  168. case TAB2: fprintf(stdout, "tab2 "); printed = 1; break;
  169. case TAB3: fprintf(stdout, "tab3 "); printed = 1; break;
  170. }
  171. switch ((t.c_oflag & BSDLY)) {
  172. case BS0: if (!hide_defaults) { fprintf(stdout, "bs0 "); printed = 1; } break;
  173. case BS1: fprintf(stdout, "bs1 "); printed = 1; break;
  174. }
  175. switch ((t.c_oflag & FFDLY)) {
  176. case FF0: if (!hide_defaults) { fprintf(stdout, "ff0 "); printed = 1; } break;
  177. case FF1: fprintf(stdout, "ff1 "); printed = 1; break;
  178. }
  179. switch ((t.c_oflag & VTDLY)) {
  180. case VT0: if (!hide_defaults) { fprintf(stdout, "vt0"); printed = 1; } break;
  181. case VT1: fprintf(stdout, "vt1"); printed = 1; break;
  182. }
  183. if (printed) { fprintf(stdout, "\n"); printed = 0; }
  184. print_lflag("isig", ISIG, 1);
  185. print_lflag("icanon", ICANON, 1);
  186. print_lflag("xcase", XCASE, 0);
  187. print_lflag("echo", ECHO, 1);
  188. print_lflag("echoe", ECHOE, 1);
  189. print_lflag("echok", ECHOK, 1);
  190. print_lflag("echonl", ECHONL, 0);
  191. print_lflag("noflsh", NOFLSH, 0);
  192. print_lflag("tostop", TOSTOP, 0);
  193. print_lflag("iexten", IEXTEN, 1);
  194. if (printed) { fprintf(stdout, "\n"); printed = 0; }
  195. return 0;
  196. }
  197. static void show_size(void) {
  198. struct winsize w;
  199. ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
  200. fprintf(stdout, "%d %d\n", w.ws_row, w.ws_col);
  201. }
  202. int main(int argc, char * argv[]) {
  203. int i = 1;
  204. if (i < argc && !strcmp(argv[i], "-a")) {
  205. hide_defaults = 0;
  206. i++;
  207. }
  208. if (i == argc) {
  209. return show_settings(0);
  210. }
  211. struct termios t;
  212. tcgetattr(STDERR_FILENO, &t);
  213. while (i < argc) {
  214. if (!strcmp(argv[i], "sane")) {
  215. t.c_iflag = ICRNL | BRKINT;
  216. t.c_oflag = ONLCR | OPOST;
  217. t.c_lflag = ECHO | ECHOE | ECHOK | ICANON | ISIG | IEXTEN;
  218. t.c_cflag = CREAD | CS8;
  219. t.c_cc[VEOF] = 4; /* ^D */
  220. t.c_cc[VEOL] = 0; /* Not set */
  221. t.c_cc[VERASE] = 0x7F; /* ^? */
  222. t.c_cc[VINTR] = 3; /* ^C */
  223. t.c_cc[VKILL] = 21; /* ^U */
  224. t.c_cc[VMIN] = 1;
  225. t.c_cc[VQUIT] = 28; /* ^\ */
  226. t.c_cc[VSTART] = 17; /* ^Q */
  227. t.c_cc[VSTOP] = 19; /* ^S */
  228. t.c_cc[VSUSP] = 26; /* ^Z */
  229. t.c_cc[VTIME] = 0;
  230. t.c_cc[VLNEXT] = 22; /* ^V */
  231. t.c_cc[VWERASE] = 23; /* ^W */
  232. i++;
  233. continue;
  234. }
  235. if (!strcmp(argv[i], "size")) {
  236. show_size();
  237. i++;
  238. continue;
  239. }
  240. set_char("eof", VEOF);
  241. set_char("eol", VEOL);
  242. set_char("erase", VERASE);
  243. set_char("intr", VINTR);
  244. set_char("kill", VKILL);
  245. set_char("quit", VQUIT);
  246. set_char("start", VSTART);
  247. set_char("stop", VSTOP);
  248. set_char("susp", VSUSP);
  249. set_char("lnext", VLNEXT);
  250. set_char("vwerase",VWERASE);
  251. set_cflag("parenb", PARENB);
  252. set_cflag("parodd", PARODD);
  253. set_cflag("hupcl", HUPCL);
  254. set_cflag("hup", HUPCL); /* alias */
  255. set_cflag("cstopb", CSTOPB);
  256. set_cflag("cread", CREAD);
  257. set_cflag("clocal", CLOCAL);
  258. set_ctoggle("cs5", CSIZE, CS5);
  259. set_ctoggle("cs6", CSIZE, CS6);
  260. set_ctoggle("cs7", CSIZE, CS7);
  261. set_ctoggle("cs8", CSIZE, CS8);
  262. set_iflag("ignbrk", IGNBRK);
  263. set_iflag("brkint", BRKINT);
  264. set_iflag("ignpar", IGNPAR);
  265. set_iflag("parmrk", PARMRK);
  266. set_iflag("inpck", INPCK);
  267. set_iflag("istrip", ISTRIP);
  268. set_iflag("inlcr", INLCR);
  269. set_iflag("igncr", IGNCR);
  270. set_iflag("icrnl", ICRNL);
  271. set_iflag("ixon", IXON);
  272. set_iflag("ixany", IXANY);
  273. set_iflag("ixoff", IXOFF);
  274. set_oflag("olcuc", OLCUC);
  275. set_oflag("opost", OPOST);
  276. set_oflag("onlcr", ONLCR);
  277. set_oflag("ocrnl", OCRNL);
  278. set_oflag("onocr", ONOCR);
  279. set_oflag("onlret", ONLRET);
  280. set_oflag("ofill", OFILL);
  281. set_oflag("ofdel", OFDEL);
  282. set_otoggle("cr0", CRDLY, CR0);
  283. set_otoggle("cr1", CRDLY, CR1);
  284. set_otoggle("cr2", CRDLY, CR2);
  285. set_otoggle("cr3", CRDLY, CR3);
  286. set_otoggle("nl0", NLDLY, NL0);
  287. set_otoggle("nl1", NLDLY, NL1);
  288. set_otoggle("tab0", TABDLY, TAB0);
  289. set_otoggle("tab1", TABDLY, TAB1);
  290. set_otoggle("tab2", TABDLY, TAB2);
  291. set_otoggle("tab3", TABDLY, TAB3);
  292. set_otoggle("bs0", BSDLY, BS0);
  293. set_otoggle("bs1", BSDLY, BS1);
  294. set_otoggle("ff0", FFDLY, FF0);
  295. set_otoggle("ff1", FFDLY, FF1);
  296. set_otoggle("vt0", VTDLY, VT0);
  297. set_otoggle("vt1", VTDLY, VT1);
  298. set_lflag("isig", ISIG);
  299. set_lflag("icanon", ICANON);
  300. set_lflag("iexten", IEXTEN);
  301. set_lflag("echo", ECHO);
  302. set_lflag("echoe", ECHOE);
  303. set_lflag("echok", ECHOK);
  304. set_lflag("echonl", ECHONL);
  305. set_lflag("noflsh", NOFLSH);
  306. set_lflag("tostop", TOSTOP);
  307. fprintf(stderr, "%s: invalid argument '%s'\n", argv[0], argv[i]);
  308. return 1;
  309. }
  310. tcsetattr(STDERR_FILENO, TCSAFLUSH, &t);
  311. return 0;
  312. }