1 /*$Id: copy.c,v 1.10 1999/08/07 19:28:16 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
4 /* Copies a file relative the current directory and substitutes */
5 /* !A at the beginning of a line for the target, */
6 /* !R at the beginning of a line for the confirm reply address, */
7 /* The following substitutions are also made. If not set, ????? */
8 /* will be printed: <#l#> outlocal */
9 /* will be printed: <#h#> outhost */
10 /* will be printed: <#n#> outmsgnum */
11 /* Other tags are killed, e.g. removed. A missing file is a */
12 /* permanent error so owner finds out ASAP. May not have access to */
13 /* maillog. Content transfer encoding is done for 'B' and 'Q'. For */
14 /* 'H' no content transfer encoding is done, but blank lines are */
15 /* suppressed. Behavior for other codes is undefined. This includes*/
16 /* lower case 'q'/'b'! If code is 'H' substitution of target and */
17 /* verptarget is prevented as it may create illegal headers. */
25 #include "readwrite.h"
32 /* for public setup functions only */
33 #define FATAL "copy: fatal: "
35 static stralloc line
= {0};
36 static stralloc outline
= {0};
37 static stralloc qline
= {0};
38 static stralloc outlocal
= {0};
39 static stralloc outhost
= {0};
40 static substdio sstext
;
41 static char textbuf
[256];
42 static char *target
= "?????";
43 static char *verptarget
= "?????";
44 static char *confirm
= "?????";
45 static char *szmsgnum
= "?????";
47 void set_cpoutlocal(ln
)
49 { /* must be quoted for safety. Note that substitutions that use */
50 /* outlocal within an atom may create illegal addresses */
51 if (!quote(&outlocal
,ln
))
52 strerr_die2x(111,FATAL
,ERR_NOMEM
);
55 void set_cpouthost(ln
)
58 if (!stralloc_copy(&outhost
,ln
))
59 strerr_die2x(111,FATAL
,ERR_NOMEM
);
68 void set_cpverptarget(tg
)
74 void set_cpconfirm(cf
)
86 static struct qmail
*qq
;
88 static void codeput(l
,n
,code
,fatal
)
95 if (!code
|| code
== 'H')
99 encodeQ(l
,n
,&qline
,fatal
);
101 encodeB(l
,n
,&qline
,0,fatal
);
102 qmail_put(qq
,qline
.s
,qline
.len
);
106 static void codeputs(l
,code
,fatal
)
111 codeput(l
,str_len(l
),code
,fatal
);
114 void copy(qqp
,fn
,q
,fatal
)
116 char *fn
; /* text file name */
117 char q
; /* = '\0' for regular output, 'B' for base64, */
118 /* 'Q' for quoted printable,'H' for header */
119 char *fatal
; /* FATAL error string */
124 unsigned int pos
,nextpos
;
127 if ((fd
= open_read(fn
)) == -1)
128 if (errno
!= error_noent
)
129 strerr_die4sys(111,fatal
,ERR_OPEN
,fn
,": ");
131 strerr_die4sys(100,fatal
,ERR_OPEN
,fn
,": ");
132 substdio_fdbuf(&sstext
,read
,fd
,textbuf
,sizeof(textbuf
));
134 if (getln(&sstext
,&line
,&match
,'\n') == -1)
135 strerr_die4sys(111,fatal
,ERR_READ
,fn
,": ");
136 if (match
) { /* suppress blank line for 'H'eader mode */
137 if (line
.len
== 1 && q
== 'H') continue;
138 if (line
.s
[0] == '!') {
139 if (line
.s
[1] == 'R') {
140 codeput(" ",3,q
,fatal
);
141 codeputs(confirm
,q
,fatal
);
142 codeput("\n",1,q
,fatal
);
145 if (line
.s
[1] == 'A') {
146 codeput(" ",3,q
,fatal
);
147 codeputs(target
,q
,fatal
);
148 codeput("\n",1,q
,fatal
);
152 /* Find tags <#x#>. Replace with for x=R confirm, for x=A */
153 /* target, x=l outlocal, x=h outhost. For others, just */
154 /* skip tag. If outlocal/outhost are not set, the tags are*/
155 /* skipped. If confirm/taget are not set, the tags are */
156 /* replaced by "???????" */
160 outline
.len
= 0; /* zap outline */
161 while ((pos
+= byte_chr(line
.s
+pos
,line
.len
-pos
,'<')) != line
.len
) {
162 if (pos
+ 4 < line
.len
&&
163 line
.s
[pos
+1] == '#' &&
164 line
.s
[pos
+3] == '#' &&
165 line
.s
[pos
+4] == '>') { /* tag. Copy first part of line */
166 done
= 1; /* did something */
167 if (!stralloc_catb(&outline
,line
.s
+nextpos
,pos
-nextpos
))
169 switch(line
.s
[pos
+2]) {
171 if (q
== 'H') strerr_die(111,ERR_SUBST_UNSAFE
);
172 if (!stralloc_cats(&outline
,target
)) die_nomem(fatal
);
175 if (!stralloc_cats(&outline
,confirm
)) die_nomem(fatal
);
178 if (!stralloc_cat(&outline
,&outlocal
)) die_nomem(fatal
);
181 if (!stralloc_cat(&outline
,&outhost
)) die_nomem(fatal
);
184 if (q
== 'H') strerr_die(111,ERR_SUBST_UNSAFE
);
185 if (!stralloc_cats(&outline
,verptarget
)) die_nomem(fatal
);
188 if (!stralloc_cats(&outline
,szmsgnum
)) die_nomem(fatal
);
191 break; /* unknown tags killed */
196 ++pos
; /* try next position */
199 codeput(line
.s
,line
.len
,q
,fatal
);
201 if (!stralloc_catb(&outline
,line
.s
+nextpos
,line
.len
-nextpos
))
202 die_nomem(fatal
); /* remainder */
203 codeput(outline
.s
,outline
.len
,q
,fatal
);