Thanks to John Cummings.
This commit is contained in:
parent
9f1fdc1287
commit
d1f529f46f
27 changed files with 4344 additions and 0 deletions
155
src/cmd/upas/common/appendfiletombox.c
Normal file
155
src/cmd/upas/common/appendfiletombox.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue