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