URI:
       tappendfiletombox.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tappendfiletombox.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 }