fdmux.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. int cons = -1;
  12. void unraw(void)
  13. {
  14. if (write(cons, "rawoff", 6) < 6)
  15. fprint(2, "rawoff: %r");
  16. }
  17. void
  18. main(void)
  19. {
  20. int pid, ctl, m, s;
  21. char c[1];
  22. if (rfork(RFNAMEG) < 0)
  23. sysfatal(smprint("RFNAMEG: %r"));
  24. cons = open("/dev/consctl", OWRITE);
  25. if (cons < 0)
  26. sysfatal(smprint("%r"));
  27. if (write(cons, "rawon", 5) < 5)
  28. sysfatal(smprint("%r"));
  29. atexit(unraw);
  30. if (bind("#<", "/dev", MBEFORE) < 0)
  31. sysfatal(smprint("%r"));
  32. if ((ctl = open("/dev/consctl", ORDWR)) < 0)
  33. sysfatal(smprint("%r"));
  34. if ((m = open("/dev/m", ORDWR)) < 0)
  35. sysfatal(smprint("%r"));
  36. if ((s = open("/dev/cons", ORDWR)) < 0)
  37. sysfatal(smprint("%r"));
  38. pid = rfork(RFFDG|RFNOTEG|RFPROC);
  39. if (pid < 0)
  40. sysfatal(smprint("%r"));
  41. if (pid == 0) {
  42. dup(s, 0);
  43. dup(s, 1);
  44. dup(s, 2);
  45. close(s);
  46. close(m);
  47. execl("/bin/rc", "rc", "-m", "/rc/lib/rcmain", "-i", nil);
  48. sysfatal(smprint("%r"));
  49. }
  50. close(s);
  51. pid = fork();
  52. if (pid < 0)
  53. sysfatal(smprint("%r"));
  54. if (pid == 0) {
  55. int amt;
  56. while ((amt = read(m, c, 1)) > 0) {
  57. if (write(1, c, 1) < 1)
  58. sysfatal(smprint("%r"));
  59. }
  60. }
  61. for(;;) {
  62. int amt;
  63. amt = read(0, c, 1);
  64. if (amt < 0) {
  65. fprint(2, "EOF from fd 0\n");
  66. break;
  67. }
  68. /* we indicated ^D to the child with a zero byte write. */
  69. if (c[0] == 4) { //^D
  70. write(m, c, 0);
  71. write(1, "^D", 2);
  72. continue;
  73. }
  74. if (c[0] == 3) { //^C
  75. write(1, "^C", 2);
  76. write(ctl, "n", 1);
  77. continue;
  78. }
  79. if (c[0] == 26) { //^Z
  80. write(1, "^Z", 2);
  81. write(ctl, "s", 1);
  82. continue;
  83. }
  84. if (c[0] == '\r') {
  85. write(1, c, 1);
  86. c[0] = '\n';
  87. }
  88. if (write(1, c, 1) < 1)
  89. sysfatal(smprint("%r"));
  90. if (write(m, c, amt) < amt) {
  91. fprint(2, "%r");
  92. break;
  93. }
  94. /* for the record: it's totally legal to try to keep reading after a 0 byte
  95. * read, even on unix. This is one of those things many people don't seem
  96. * to know.
  97. */
  98. }
  99. if (write(cons, "rawoff", 6) < 6)
  100. fprint(2, "rawoff: %r");
  101. #if 0
  102. pid = rfork(RFMEM|RFPROC);
  103. if (pid < 0) {
  104. print("FAIL: rfork\n");
  105. exits("FAIL");
  106. }
  107. if (pid > 0) {
  108. c++;
  109. }
  110. if (pid == 0) {
  111. print("PASS\n");
  112. exits(nil);
  113. }
  114. if (c > 1) {
  115. print("FAIL\n");
  116. exits("FAIL");
  117. }
  118. #endif
  119. }