main.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Main program.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stddef.h>
  7. #include <stdarg.h>
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <unistd.h>
  12. #include <sys/types.h>
  13. #include <sys/wait.h>
  14. #include "sel.h"
  15. #include "pty.h"
  16. #include "telnet.h"
  17. int signalpipe[2];
  18. sel *asel;
  19. sel_rfd *netr, *ptyr, *sigr;
  20. int ptyfd;
  21. sel_wfd *netw, *ptyw;
  22. Telnet *telnet;
  23. #define BUF 65536
  24. void sigchld(int signum)
  25. {
  26. write(signalpipe[1], "C", 1);
  27. }
  28. void fatal(const char *fmt, ...)
  29. {
  30. va_list ap;
  31. fprintf(stderr, "cygtermd: ");
  32. va_start(ap, fmt);
  33. vfprintf(stderr, fmt, ap);
  34. va_end(ap);
  35. fprintf(stderr, "\n");
  36. exit(1);
  37. }
  38. void net_readdata(sel_rfd *rfd, void *data, size_t len)
  39. {
  40. if (len == 0)
  41. exit(0); /* EOF on network - client went away */
  42. telnet_from_net(telnet, data, len);
  43. if (sel_write(netw, NULL, 0) > BUF)
  44. sel_rfd_freeze(ptyr);
  45. if (sel_write(ptyw, NULL, 0) > BUF)
  46. sel_rfd_freeze(netr);
  47. }
  48. void net_readerr(sel_rfd *rfd, int error)
  49. {
  50. fprintf(stderr, "standard input: read: %s\n", strerror(errno));
  51. exit(1);
  52. }
  53. void net_written(sel_wfd *wfd, size_t bufsize)
  54. {
  55. if (bufsize < BUF)
  56. sel_rfd_unfreeze(ptyr);
  57. }
  58. void net_writeerr(sel_wfd *wfd, int error)
  59. {
  60. fprintf(stderr, "standard input: write: %s\n", strerror(errno));
  61. exit(1);
  62. }
  63. void pty_readdata(sel_rfd *rfd, void *data, size_t len)
  64. {
  65. if (len == 0)
  66. exit(0); /* EOF on pty */
  67. telnet_from_pty(telnet, data, len);
  68. if (sel_write(netw, NULL, 0) > BUF)
  69. sel_rfd_freeze(ptyr);
  70. if (sel_write(ptyw, NULL, 0) > BUF)
  71. sel_rfd_freeze(netr);
  72. }
  73. void pty_readerr(sel_rfd *rfd, int error)
  74. {
  75. if (error == EIO) /* means EOF, on a pty */
  76. exit(0);
  77. fprintf(stderr, "pty: read: %s\n", strerror(errno));
  78. exit(1);
  79. }
  80. void pty_written(sel_wfd *wfd, size_t bufsize)
  81. {
  82. if (bufsize < BUF)
  83. sel_rfd_unfreeze(netr);
  84. }
  85. void pty_writeerr(sel_wfd *wfd, int error)
  86. {
  87. fprintf(stderr, "pty: write: %s\n", strerror(errno));
  88. exit(1);
  89. }
  90. void sig_readdata(sel_rfd *rfd, void *data, size_t len)
  91. {
  92. char *p = data;
  93. while (len > 0) {
  94. if (*p == 'C') {
  95. int status;
  96. waitpid(-1, &status, WNOHANG);
  97. if (WIFEXITED(status) || WIFSIGNALED(status))
  98. exit(0); /* child process vanished */
  99. }
  100. }
  101. }
  102. void sig_readerr(sel_rfd *rfd, int error)
  103. {
  104. fprintf(stderr, "signal pipe: read: %s\n", strerror(errno));
  105. exit(1);
  106. }
  107. int main(int argc, char **argv)
  108. {
  109. int ret;
  110. int shell_started = 0;
  111. char *directory = NULL;
  112. char **program_args = NULL;
  113. if (argc > 1 && argv[1][0]) {
  114. directory = argv[1];
  115. argc--, argv++;
  116. }
  117. if (argc > 1) {
  118. program_args = argv + 1;
  119. }
  120. pty_preinit();
  121. asel = sel_new(NULL);
  122. netr = sel_rfd_add(asel, 0, net_readdata, net_readerr, NULL);
  123. netw = sel_wfd_add(asel, 1, net_written, net_writeerr, NULL);
  124. ptyr = sel_rfd_add(asel, -1, pty_readdata, pty_readerr, NULL);
  125. ptyw = sel_wfd_add(asel, -1, pty_written, pty_writeerr, NULL);
  126. telnet = telnet_new(netw, ptyw);
  127. if (pipe(signalpipe) < 0) {
  128. perror("pipe");
  129. return 1;
  130. }
  131. sigr = sel_rfd_add(asel, signalpipe[0], sig_readdata,
  132. sig_readerr, NULL);
  133. signal(SIGCHLD, sigchld);
  134. do {
  135. struct shell_data shdata;
  136. ret = sel_iterate(asel, -1);
  137. if (!shell_started && telnet_shell_ok(telnet, &shdata)) {
  138. ptyfd = run_program_in_pty(&shdata, directory, program_args);
  139. sel_rfd_setfd(ptyr, ptyfd);
  140. sel_wfd_setfd(ptyw, ptyfd);
  141. shell_started = 1;
  142. }
  143. } while (ret == 0);
  144. return 0;
  145. }