stty.c 3.8 KB

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