fdlink.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #include <sys/select.h>
  2. #include <sys/types.h>
  3. #include <sys/wait.h>
  4. #include <unistd.h>
  5. #include <stdio.h>
  6. #include <fcntl.h>
  7. #include <signal.h>
  8. #include <errno.h>
  9. #include <stdlib.h>
  10. #include <assert.h>
  11. #define safe(expr, error) do { if (!(expr)) { perror(error); exit(1); } } while (0)
  12. static sig_atomic_t exited;
  13. static void
  14. sighandler(int sig)
  15. {
  16. if (sig == SIGCHLD)
  17. exited = 1;
  18. }
  19. int
  20. main(int argc, char **argv)
  21. {
  22. pid_t pid;
  23. if (argc < 2) {
  24. fprintf(stderr, "usage: fdlink bin args...\n");
  25. exit(2);
  26. }
  27. signal(SIGCHLD, sighandler);
  28. if ((pid = fork()) == 0) {
  29. close(0);
  30. safe(execv(argv[1], argv + 1) != -1, "fdlink execv");
  31. /* NOTREACHED */
  32. } else {
  33. assert(pid != -1);
  34. safe(fcntl(0, F_SETFL, O_NONBLOCK) != -1, "fdlink fcntl");
  35. int nfds;
  36. do {
  37. if (exited == 1) {
  38. int status;
  39. if (waitpid(pid, &status, WNOHANG) != -1) {
  40. exit(WEXITSTATUS(status));
  41. };
  42. exited = 0;
  43. }
  44. fd_set fdset_r; FD_ZERO(&fdset_r); FD_SET(0, &fdset_r);
  45. fd_set fdset_e; FD_ZERO(&fdset_e); FD_SET(0, &fdset_e);
  46. nfds = select(64, &fdset_r, NULL, &fdset_e, NULL);
  47. if (nfds == -1 && (errno == EAGAIN || errno == EINTR))
  48. continue;
  49. else if (nfds == -1) {
  50. perror("fdlink select");
  51. exit(1);
  52. }
  53. if (FD_ISSET(0, &fdset_r) || FD_ISSET(0, &fdset_e)) {
  54. char buf[1024];
  55. while (1) {
  56. int nread = read(0, &buf, sizeof(buf));
  57. if (nread == -1 && errno == EINTR)
  58. continue;
  59. else if (nread == -1 && errno == EAGAIN)
  60. break;
  61. else if (nread == -1) {
  62. perror("fdlink read");
  63. exit(1);
  64. } else if (nread == 0) {
  65. kill(pid, SIGHUP);
  66. exit(0);
  67. }
  68. }
  69. }
  70. } while (1);
  71. }
  72. return 0;
  73. }