catcher.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #undef VERBOSE
  2. #include <stdio.h>
  3. #include <signal.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <errno.h>
  7. #include <sys/types.h>
  8. #include <termios.h>
  9. #ifdef __FreeBSD__
  10. #include <sys/ttydefaults.h>
  11. #else
  12. #define CTRL(x) (x&037)
  13. #define CEOF CTRL('d')
  14. #endif
  15. #define BUFSIZE 65536
  16. struct termios ttystate;
  17. struct termios oldttystate;
  18. int cleanupP = 0;
  19. #ifndef CTRL
  20. #define CTRL(x) (x&037)
  21. #endif
  22. int _global_fd;
  23. void handler2(int sig);
  24. void handler3(int sig);
  25. void cleanup(void);
  26. void handler2(int sig)
  27. {
  28. #define TMP "Async action on sigint (2)\n"
  29. write(1,TMP,sizeof(TMP)-1);
  30. #undef TMP
  31. }
  32. void handler3(int sig)
  33. {
  34. #define TMP "Async action on sigquit (3)\n"
  35. write(1,TMP,sizeof(TMP)-1);
  36. #undef TMP
  37. }
  38. void cleanup()
  39. {
  40. if (cleanupP) {
  41. printf("Resettung terminal\n");
  42. if (tcsetattr(_global_fd, TCSANOW, &oldttystate) < 0) {
  43. perror("ioctl reset /dev/tty");
  44. }
  45. }
  46. close(_global_fd);
  47. }
  48. static void exit_handler(int sig)
  49. #ifdef __GNUC__
  50. __attribute__ ((noreturn))
  51. #endif
  52. ;
  53. static void exit_handler(int sig)
  54. {
  55. cleanup();
  56. if (sig)
  57. printf("Exiting on signal %d\n",sig);
  58. exit(0);
  59. }
  60. int main(void)
  61. {
  62. char c[BUFSIZE];
  63. pid_t pgrp;
  64. #ifdef VERBOSE
  65. printf("I'm PID %d\n",getpid());
  66. #endif
  67. if ( ( _global_fd = open("/dev/tty",O_RDONLY)) < 1) {
  68. perror("open /dev/tty");
  69. exit_handler(0);
  70. }
  71. if ( (pgrp = tcgetpgrp(_global_fd)) < 0) {
  72. perror("Can't get pgrp\n");
  73. exit_handler(0);
  74. }
  75. #ifdef VERBOSE
  76. printf("tty pgrp is %ld\n",(long)pgrp);
  77. #endif
  78. if ( tcsetpgrp(_global_fd, pgrp) < 0) {
  79. perror("Can't set pgrp\n");
  80. exit_handler(0);
  81. }
  82. if (tcgetattr(_global_fd, &oldttystate) < 0) {
  83. perror("ioctl1 /dev/tty");
  84. exit_handler(0);
  85. }
  86. ttystate = oldttystate;
  87. ttystate.c_lflag &= ~ICANON;
  88. ttystate.c_lflag &= ~ECHO;
  89. ttystate.c_cc[VQUIT] = CTRL('g'); /* From sys/ttydefaults.h */
  90. if (tcsetattr(_global_fd, TCSANOW, &ttystate) < 0) {
  91. perror("ioctl2 /dev/tty");
  92. exit_handler(0);
  93. }
  94. cleanupP = 1;
  95. {
  96. struct sigaction siga;
  97. sigemptyset(&siga.sa_mask);
  98. siga.sa_flags = 0;
  99. siga.sa_handler = handler2;
  100. sigaction(SIGINT, &siga, (struct sigaction *)0);
  101. siga.sa_handler = handler3;
  102. sigaction(SIGQUIT, &siga, (struct sigaction *)0);
  103. siga.sa_handler = exit_handler;
  104. sigaction(SIGHUP, &siga, (struct sigaction *)0);
  105. sigaction(SIGTERM, &siga, (struct sigaction *)0);
  106. }
  107. printf("Use C-c and C-g for async actions, end with C-d\n");
  108. while (1) {
  109. switch (read(_global_fd,c,1)) {
  110. case -1:
  111. if (errno == EINTR)
  112. continue;
  113. perror("stdin read");
  114. exit_handler(0);
  115. case 0:
  116. printf("Exiting on stdin EOF (should happen only in cannon mode\n");
  117. exit_handler(0);
  118. default:
  119. if (c[0] == CEOF) { /* From sys/ttydefaults.h */
  120. printf("Exiting on stdin EOF (hopefully only in noncannon mode)\n");
  121. exit_handler(0);
  122. }
  123. printf("You typed: '%c' (0x%X)\n",c[0],c[0]);
  124. }
  125. }
  126. exit_handler(0);
  127. return 0;
  128. }