123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #include "common.h"
- enum {
- Buffersize = 64*1024,
- };
- typedef struct Inbuf Inbuf;
- struct Inbuf
- {
- char buf[Buffersize];
- char *wp;
- char *rp;
- int eof;
- int in;
- int out;
- int last;
- ulong bytes;
- };
- static Inbuf*
- allocinbuf(int in, int out)
- {
- Inbuf *b;
- b = mallocz(sizeof(Inbuf), 1);
- if(b == nil)
- sysfatal("reading mailbox: %r");
- b->rp = b->wp = b->buf;
- b->in = in;
- b->out = out;
- return b;
- }
- static int
- fill(Inbuf *b, int addspace)
- {
- int i, n;
- if(b->eof && b->wp - b->rp == 0)
- return 0;
- n = b->rp - b->buf;
- if(n > 0){
- i = write(b->out, b->buf, n);
- if(i != n)
- return -1;
- b->last = b->buf[n-1];
- b->bytes += n;
- }
- if(addspace){
- if(write(b->out, " ", 1) != 1)
- return -1;
- b->last = ' ';
- b->bytes++;
- }
- n = b->wp - b->rp;
- memmove(b->buf, b->rp, n);
- b->rp = b->buf;
- b->wp = b->rp + n;
- i = read(b->in, b->buf+n, sizeof(b->buf)-n);
- if(i < 0)
- return -1;
- b->wp += i;
- return b->wp - b->rp;
- }
- /* code to escape ' '*From' ' at the beginning of a line */
- int
- appendfiletombox(int in, int out)
- {
- int addspace;
- int n;
- char *p;
- int sol;
- Inbuf *b;
- seek(out, 0, 2);
- b = allocinbuf(in, out);
- addspace = 0;
- sol = 1;
- for(;;){
- if(b->wp - b->rp < 5){
- n = fill(b, addspace);
- addspace = 0;
- if(n < 0)
- goto error;
- if(n == 0)
- break;
- if(n < 5){
- b->rp = b->wp;
- continue;
- }
- }
- /* state machine looking for ' '*From' ' */
- if(!sol){
- p = memchr(b->rp, '\n', b->wp - b->rp);
- if(p == nil)
- b->rp = b->wp;
- else{
- b->rp = p+1;
- sol = 1;
- }
- continue;
- } else {
- if(*b->rp == ' ' || strncmp(b->rp, "From ", 5) != 0){
- b->rp++;
- continue;
- }
- addspace = 1;
- sol = 0;
- }
- }
- /* mailbox entries always terminate with two newlines */
- n = b->last == '\n' ? 1 : 2;
- if(write(out, "\n\n", n) != n)
- goto error;
- n += b->bytes;
- free(b);
- return n;
- error:
- free(b);
- return -1;
- }
- int
- appendfiletofile(int in, int out)
- {
- int n;
- Inbuf *b;
- seek(out, 0, 2);
- b = allocinbuf(in, out);
- for(;;){
- n = fill(b, 0);
- if(n < 0)
- goto error;
- if(n == 0)
- break;
- b->rp = b->wp;
- }
- n = b->bytes;
- free(b);
- return n;
- error:
- free(b);
- return -1;
- }
|