plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

appendfiletombox.c (2153B)


      1 #include "common.h"
      2 
      3 enum {
      4 	Buffersize = 64*1024
      5 };
      6 
      7 typedef struct Inbuf Inbuf;
      8 struct Inbuf
      9 {
     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 };
     19 
     20 static Inbuf*
     21 allocinbuf(int in, int out)
     22 {
     23 	Inbuf *b;
     24 
     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 }
     33 
     34 static int
     35 fill(Inbuf *b, int addspace)
     36 {
     37 	int i, n;
     38 
     39 	if(b->eof && b->wp - b->rp == 0)
     40 		return 0;
     41 
     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 	}
     56 
     57 	n = b->wp - b->rp;
     58 	memmove(b->buf, b->rp, n);
     59 	b->rp = b->buf;
     60 	b->wp = b->rp + n;
     61 
     62 	i = read(b->in, b->buf+n, sizeof(b->buf)-n);
     63 	if(i < 0)
     64 		return -1;
     65 	b->wp += i;
     66 
     67 	return b->wp - b->rp;
     68 }
     69 
     70 /* code to escape ' '*From' ' at the beginning of a line */
     71 int
     72 appendfiletombox(int in, int out)
     73 {
     74 	int addspace;
     75 	int n;
     76 	char *p;
     77 	int sol;
     78 	Inbuf *b;
     79 
     80 	seek(out, 0, 2);
     81 
     82 	b = allocinbuf(in, out);
     83 	addspace = 0;
     84 	sol = 1;
     85 
     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 		}
     99 
    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 	}
    119 
    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 }
    131 
    132 int
    133 appendfiletofile(int in, int out)
    134 {
    135 	int n;
    136 	Inbuf *b;
    137 
    138 	seek(out, 0, 2);
    139 
    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 }