appendfiletombox.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #include "common.h"
  2. enum {
  3. Buffersize = 64*1024,
  4. };
  5. typedef struct Inbuf Inbuf;
  6. struct Inbuf
  7. {
  8. char buf[Buffersize];
  9. char *wp;
  10. char *rp;
  11. int eof;
  12. int in;
  13. int out;
  14. int last;
  15. ulong bytes;
  16. };
  17. static Inbuf*
  18. allocinbuf(int in, int out)
  19. {
  20. Inbuf *b;
  21. b = mallocz(sizeof(Inbuf), 1);
  22. if(b == nil)
  23. sysfatal("reading mailbox: %r");
  24. b->rp = b->wp = b->buf;
  25. b->in = in;
  26. b->out = out;
  27. return b;
  28. }
  29. static int
  30. fill(Inbuf *b, int addspace)
  31. {
  32. int i, n;
  33. if(b->eof && b->wp - b->rp == 0)
  34. return 0;
  35. n = b->rp - b->buf;
  36. if(n > 0){
  37. i = write(b->out, b->buf, n);
  38. if(i != n)
  39. return -1;
  40. b->last = b->buf[n-1];
  41. b->bytes += n;
  42. }
  43. if(addspace){
  44. if(write(b->out, " ", 1) != 1)
  45. return -1;
  46. b->last = ' ';
  47. b->bytes++;
  48. }
  49. n = b->wp - b->rp;
  50. memmove(b->buf, b->rp, n);
  51. b->rp = b->buf;
  52. b->wp = b->rp + n;
  53. i = read(b->in, b->buf+n, sizeof(b->buf)-n);
  54. if(i < 0)
  55. return -1;
  56. b->wp += i;
  57. return b->wp - b->rp;
  58. }
  59. /* code to escape ' '*From' ' at the beginning of a line */
  60. int
  61. appendfiletombox(int in, int out)
  62. {
  63. int addspace;
  64. int n;
  65. char *p;
  66. int sol;
  67. Inbuf *b;
  68. seek(out, 0, 2);
  69. b = allocinbuf(in, out);
  70. addspace = 0;
  71. sol = 1;
  72. for(;;){
  73. if(b->wp - b->rp < 5){
  74. n = fill(b, addspace);
  75. addspace = 0;
  76. if(n < 0)
  77. goto error;
  78. if(n == 0)
  79. break;
  80. if(n < 5){
  81. b->rp = b->wp;
  82. continue;
  83. }
  84. }
  85. /* state machine looking for ' '*From' ' */
  86. if(!sol){
  87. p = memchr(b->rp, '\n', b->wp - b->rp);
  88. if(p == nil)
  89. b->rp = b->wp;
  90. else{
  91. b->rp = p+1;
  92. sol = 1;
  93. }
  94. continue;
  95. } else {
  96. if(*b->rp == ' ' || strncmp(b->rp, "From ", 5) != 0){
  97. b->rp++;
  98. continue;
  99. }
  100. addspace = 1;
  101. sol = 0;
  102. }
  103. }
  104. /* mailbox entries always terminate with two newlines */
  105. n = b->last == '\n' ? 1 : 2;
  106. if(write(out, "\n\n", n) != n)
  107. goto error;
  108. n += b->bytes;
  109. free(b);
  110. return n;
  111. error:
  112. free(b);
  113. return -1;
  114. }
  115. int
  116. appendfiletofile(int in, int out)
  117. {
  118. int n;
  119. Inbuf *b;
  120. seek(out, 0, 2);
  121. b = allocinbuf(in, out);
  122. for(;;){
  123. n = fill(b, 0);
  124. if(n < 0)
  125. goto error;
  126. if(n == 0)
  127. break;
  128. b->rp = b->wp;
  129. }
  130. n = b->bytes;
  131. free(b);
  132. return n;
  133. error:
  134. free(b);
  135. return -1;
  136. }