Download | Plain Text | No Line Numbers


  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <stdlib.h>
  6. #include <signal.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <sys/wait.h>
  10.  
  11. // gcc -std=c99
  12.  
  13. static char *sendmail = "/var/qmail/bin/sendmail";
  14.  
  15. int fd_copy(int to, int from)
  16. {
  17. if (to == from)
  18. return 0;
  19. if (fcntl(from, F_GETFL, 0) == -1)
  20. return -1;
  21. close(to);
  22. if (fcntl(from, F_DUPFD, to) == -1)
  23. return -1;
  24. return 0;
  25. }
  26.  
  27. void sig_catch(int sig, void (*f)())
  28. {
  29. #ifdef HASSIGACTION
  30. struct sigaction sa;
  31. sa.sa_handler = f;
  32. sa.sa_flags = 0;
  33. sigemptyset(&sa.sa_mask);
  34. sigaction(sig, &sa, (struct sigaction *)0);
  35. #else
  36. signal(sig, f);
  37. #endif
  38. }
  39.  
  40. int wait_pid(int *wstat, int pid)
  41. {
  42. int r;
  43. do
  44. r = waitpid(pid, wstat, 0);
  45. while (r == -1 && errno == EINTR);
  46. return r;
  47. }
  48.  
  49. int main(int argc, char *argv[])
  50. {
  51. for(int i = 0; i < argc; i++)
  52. {
  53. if (!strcmp(argv[i], "<>"))
  54. argv[i][0] = '\0';
  55. }
  56. argv[0] = sendmail;
  57.  
  58. int pi[2], pid;
  59. if (pipe(pi) == -1)
  60. {
  61. fprintf(stderr, "sendmail: unable to open pipe\n");
  62. exit(100);
  63. }
  64.  
  65. switch(pid = fork())
  66. {
  67. case -1:
  68. fprintf(stderr, "sendmail: unable to fork\n");
  69. exit(100);
  70. case 0:
  71. close(pi[1]);
  72. if (fd_copy(0, pi[0]) == -1)
  73. {
  74. fprintf(stderr, "sendmail: unable to copy pipe to stdin\n");
  75. exit(100);
  76. }
  77. sig_catch(SIGPIPE, SIG_DFL);
  78. execv(argv[0], argv);
  79. fprintf(stderr, "sendmail: unable to run sendmail\n");
  80. exit(111);
  81. }
  82. close(pi[0]);
  83.  
  84. char *r, buf[255];
  85. while(r = fgets(buf, sizeof(buf), stdin))
  86. {
  87. if (ferror(stdin))
  88. {
  89. fprintf(stderr, "sendmail: error while readin stdin: %s\n",
  90. strerror(fileno(stdin)));
  91. exit(111);
  92. }
  93.  
  94. int len = strlen(buf);
  95. if (len >= 2 && buf[len - 2] == '\r' && buf[len - 1] == '\n')
  96. {
  97. buf[len - 2] = buf[len - 1];
  98. buf[len - 1] = '\0';
  99. len--;
  100. }
  101. write(pi[1], buf, len);
  102. if (feof(stdin))
  103. break;
  104. }
  105. close(pi[1]);
  106.  
  107. int wstat;
  108. if (wait_pid(&wstat, pid) == -1)
  109. exit(111);
  110. exit(wstat >> 8);
  111. }
  112.