X-Git-Url: https://git.distorted.org.uk/~mdw/ezmlm/blobdiff_plain/5b62e993b0af39700031c2875d7f6654e6a02850..f8beb284087c279acfb30506f5bb32baa4949b44:/copy.c diff --git a/copy.c b/copy.c new file mode 100644 index 0000000..24f0034 --- /dev/null +++ b/copy.c @@ -0,0 +1,211 @@ +/*$Id: copy.c,v 1.10 1999/08/07 19:28:16 lindberg Exp $*/ +/*$Name: ezmlm-idx-040 $*/ + +/* Copies a file relative the current directory and substitutes */ +/* !A at the beginning of a line for the target, */ +/* !R at the beginning of a line for the confirm reply address, */ +/* The following substitutions are also made. If not set, ????? */ +/* will be printed: <#l#> outlocal */ +/* will be printed: <#h#> outhost */ +/* will be printed: <#n#> outmsgnum */ +/* Other tags are killed, e.g. removed. A missing file is a */ +/* permanent error so owner finds out ASAP. May not have access to */ +/* maillog. Content transfer encoding is done for 'B' and 'Q'. For */ +/* 'H' no content transfer encoding is done, but blank lines are */ +/* suppressed. Behavior for other codes is undefined. This includes*/ +/* lower case 'q'/'b'! If code is 'H' substitution of target and */ +/* verptarget is prevented as it may create illegal headers. */ + +#include "stralloc.h" +#include "substdio.h" +#include "strerr.h" +#include "str.h" +#include "getln.h" +#include "case.h" +#include "readwrite.h" +#include "qmail.h" +#include "errtxt.h" +#include "error.h" +#include "quote.h" +#include "copy.h" +#include "mime.h" + /* for public setup functions only */ +#define FATAL "copy: fatal: " + +static stralloc line = {0}; +static stralloc outline = {0}; +static stralloc qline = {0}; +static stralloc outlocal = {0}; +static stralloc outhost = {0}; +static substdio sstext; +static char textbuf[256]; +static char *target = "?????"; +static char *verptarget = "?????"; +static char *confirm = "?????"; +static char *szmsgnum = "?????"; + +void set_cpoutlocal(ln) +stralloc *ln; +{ /* must be quoted for safety. Note that substitutions that use */ + /* outlocal within an atom may create illegal addresses */ + if (!quote(&outlocal,ln)) + strerr_die2x(111,FATAL,ERR_NOMEM); +} + +void set_cpouthost(ln) +stralloc *ln; +{ + if (!stralloc_copy(&outhost,ln)) + strerr_die2x(111,FATAL,ERR_NOMEM); +} + +void set_cptarget(tg) +char *tg; +{ + target = tg; +} + +void set_cpverptarget(tg) +char *tg; +{ + verptarget = tg; +} + +void set_cpconfirm(cf) +char *cf; +{ + confirm = cf; +} + +void set_cpnum(cf) +char *cf; +{ + szmsgnum = cf; +} + +static struct qmail *qq; + +static void codeput(l,n,code,fatal) +char *l; +unsigned int n; +char code; +char *fatal; + +{ + if (!code || code == 'H') + qmail_put(qq,l,n); + else { + if (code == 'Q') + encodeQ(l,n,&qline,fatal); + else + encodeB(l,n,&qline,0,fatal); + qmail_put(qq,qline.s,qline.len); + } +} + +static void codeputs(l,code,fatal) +char *l; +char code; +char *fatal; +{ + codeput(l,str_len(l),code,fatal); +} + +void copy(qqp,fn,q,fatal) +struct qmail *qqp; +char *fn; /* text file name */ +char q; /* = '\0' for regular output, 'B' for base64, */ + /* 'Q' for quoted printable,'H' for header */ +char *fatal; /* FATAL error string */ + +{ + int fd; + int match, done; + unsigned int pos,nextpos; + + qq = qqp; + if ((fd = open_read(fn)) == -1) + if (errno != error_noent) + strerr_die4sys(111,fatal,ERR_OPEN,fn,": "); + else + strerr_die4sys(100,fatal,ERR_OPEN,fn,": "); + substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); + for (;;) { + if (getln(&sstext,&line,&match,'\n') == -1) + strerr_die4sys(111,fatal,ERR_READ,fn,": "); + if (match) { /* suppress blank line for 'H'eader mode */ + if (line.len == 1 && q == 'H') continue; + if (line.s[0] == '!') { + if (line.s[1] == 'R') { + codeput(" ",3,q,fatal); + codeputs(confirm,q,fatal); + codeput("\n",1,q,fatal); + continue; + } + if (line.s[1] == 'A') { + codeput(" ",3,q,fatal); + codeputs(target,q,fatal); + codeput("\n",1,q,fatal); + continue; + } + } + /* Find tags <#x#>. Replace with for x=R confirm, for x=A */ + /* target, x=l outlocal, x=h outhost. For others, just */ + /* skip tag. If outlocal/outhost are not set, the tags are*/ + /* skipped. If confirm/taget are not set, the tags are */ + /* replaced by "???????" */ + pos = 0; + nextpos = 0; + done = 0; + outline.len = 0; /* zap outline */ + while ((pos += byte_chr(line.s+pos,line.len-pos,'<')) != line.len) { + if (pos + 4 < line.len && + line.s[pos+1] == '#' && + line.s[pos+3] == '#' && + line.s[pos+4] == '>') { /* tag. Copy first part of line */ + done = 1; /* did something */ + if (!stralloc_catb(&outline,line.s+nextpos,pos-nextpos)) + die_nomem(fatal); + switch(line.s[pos+2]) { + case 'A': + if (q == 'H') strerr_die(111,ERR_SUBST_UNSAFE); + if (!stralloc_cats(&outline,target)) die_nomem(fatal); + break; + case 'R': + if (!stralloc_cats(&outline,confirm)) die_nomem(fatal); + break; + case 'l': + if (!stralloc_cat(&outline,&outlocal)) die_nomem(fatal); + break; + case 'h': + if (!stralloc_cat(&outline,&outhost)) die_nomem(fatal); + break; + case 't': + if (q == 'H') strerr_die(111,ERR_SUBST_UNSAFE); + if (!stralloc_cats(&outline,verptarget)) die_nomem(fatal); + break; + case 'n': + if (!stralloc_cats(&outline,szmsgnum)) die_nomem(fatal); + break; + default: + break; /* unknown tags killed */ + } + pos += 5; + nextpos = pos; + } else + ++pos; /* try next position */ + } + if (!done) + codeput(line.s,line.len,q,fatal); + else { + if (!stralloc_catb(&outline,line.s+nextpos,line.len-nextpos)) + die_nomem(fatal); /* remainder */ + codeput(outline.s,outline.len,q,fatal); + } + + } else + break; + } + close(fd); +} +