1 /*
2  *  TEMPLATE.C
3  *
4  *  Written on 10-Jul-94 by John Dennis and released to the public domain.
5  *
6  *  Handles the creation of messages from a template.
7  */
8 
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <time.h>
12 #include <string.h>
13 #include "addr.h"
14 #include "nedit.h"
15 #include "msged.h"
16 #include "quote.h"
17 #include "date.h"
18 #include "memextra.h"
19 #include "readmail.h"  /* GetOrigin */
20 #include "template.h"
21 #include "version.h"
22 
23 #if defined(UNIX)
24 #include <sys/utsname.h>
25 #define HAVE_UNAME
26 #endif
27 
28 
29 #define TEXTLEN 250
30 
31 static LINE* addline(LINE* ln,  char *l);
32 
parse_words_to_array(char * string,int nmembers)33 static char **parse_words_to_array(char *string, int nmembers)
34 {
35     char *cp = strtok(string, " \t\r\n");
36     int n=0;
37     char **whereto = xmalloc(nmembers * sizeof(char **));
38 
39     while (cp != NULL && n < nmembers )
40     {
41         whereto[n++] = cp;
42         cp = strtok(NULL, " \t\r\n");
43     }
44 
45     if (n < nmembers)
46     {
47         free(whereto);
48         return NULL;
49     }
50     if (cp != NULL)
51     {
52         return whereto;
53     }
54     return whereto;
55 }
56 
make_tearline(char * buf)57 void make_tearline(char *buf)
58 {
59     /* add the tearline */
60 
61     if (SW->usepid)
62     {
63         sprintf(buf, "---");
64     }
65     else
66 #ifdef HAVE_UNAME
67     if (SW->xxltearline)
68     {
69         struct utsname uts;
70         uname(&uts);
71 
72         sprintf(buf, "--- %s %s (%s/%s (%s))", PROG, VERNUM VERPATCH,
73                 uts.sysname, uts.release, uts.machine);
74     }
75     else
76 #endif
77     {
78         sprintf(buf, "--- %s %s", PROG, VERNUM VERPATCH);
79     }
80 }
81 
82 
MakeTemplateMsg(msg * m,msg * oldmsg,int olda,int type)83 int MakeTemplateMsg(msg * m, msg * oldmsg, int olda, int type)
84 {
85     LINE *ln = NULL;
86     FILE *fp = NULL;
87     char buf[TEXTLEN], buf2[TEXTLEN];
88     char *wdaybuf=NULL, *monthbuf=NULL;
89     char **use_month = NULL;
90     char **use_day   = NULL;
91     char *l;
92     int blankline;
93 
94     if (ST->template)
95     {
96         fp = fopen(ST->template, "r");
97     }
98 
99     if (!ST->template || fp == NULL)
100     {
101         if (m->text && (type & MT_QUO))
102         {
103             ln = m->text;
104             makequote(ln, oldmsg != NULL ? oldmsg->isfrom : m->isfrom);
105         }
106         return 0;
107     }
108 
109     while (fgets(buf, TEXTLEN - 1, fp))
110     {
111         if (buf[0] == ';')
112         {
113             continue;
114         }
115 
116         if (buf[0] == '@' && buf[1] && buf[1] != '@')
117         {
118             switch (tolower(buf[1]))
119             {
120             case 'w':
121                 release(wdaybuf);
122                 wdaybuf = xstrdup(buf+2);
123                 use_day = parse_words_to_array(wdaybuf, 7);
124                 continue;
125 
126             case 'o':
127                 release(monthbuf);
128                 monthbuf = xstrdup(buf+2);
129                 use_month = parse_words_to_array(monthbuf, 12);
130                 continue;
131 
132             case 'f':
133                 if (!(type & MT_FOR))
134                 {
135                     continue;
136                 }
137                 break;
138 
139             case 'l':
140                 if (!(type & MT_FOL))
141                 {
142                     continue;
143                 }
144                 break;
145 
146             case 'r':
147                 if (!(type & MT_RED))
148                 {
149                     continue;
150                 }
151                 break;
152 
153             case 'a':
154                 if (!(type & MT_ARC))
155                 {
156                     continue;
157                 }
158                 break;
159 
160             case 'q':
161                 if (!(type & MT_QUO))
162                 {
163                     continue;
164                 }
165                 break;
166 
167             case 'n':
168                 if (!(type & MT_NEW))
169                 {
170                     continue;
171                 }
172                 break;
173 
174             case 'm':
175                 if (ln)
176                 {
177                     /* assign msg to follow */
178                     ln->next = m->text;
179                     if (ln->next)
180                     {
181                         ln->next->prev = ln;
182                         ln = ln->next;
183                     }
184                 }
185                 else
186                 {
187                     ln = m->text;
188                 }
189                 if (!(type & MT_QUO))
190                 {
191                     /* don't want a quote */
192                     while (ln != NULL && ln->next != NULL)
193                     {
194                         ln = ln->next;
195                     }
196                 }
197                 else
198                 {
199                     /* we do want a quote */
200                     makequote(ln, oldmsg != NULL ? oldmsg->isfrom : m->isfrom);
201 
202                     /* just in case we didn't get the beginning */
203                     ln = m->text;
204                     while (ln != NULL && ln->next != NULL)
205                     {
206                         ln = ln->next;
207                     }
208                 }
209                 continue;
210 
211             default:
212                 /* break on things we don't know */
213                 break;
214             }
215 
216             if (buf[2])
217             {
218                 /* could be a blank line... */
219                 l = attrib_line(m, oldmsg, olda, buf + 2, use_day, use_month);
220             }
221             else
222             {
223                 l = xstrdup("\n");
224             }
225         }
226         else
227         {
228             l = attrib_line(m, oldmsg, olda, buf, use_day, use_month);
229         }
230 
231         ln = addline(ln, l);
232 
233     }
234 
235     fclose(fp);
236 
237     /* add tearline and origin if appropriate and wished */
238 
239     if (CurArea.echomail && !(type & MT_RED))
240     {
241         if (ln != NULL)
242         {
243             blankline = ( *(ln->text) == '\n');
244         }
245         else
246         {
247             blankline = 0;
248         }
249 
250         if (!(type & MT_FOR))
251         {
252             if (SW->usetearlines  && SW->useoriginlines  && !blankline &&
253                 (SW->edittearlines || SW->editoriginlines))
254             {
255                 strcpy(buf, "\n");
256                 ln = addline(ln, xstrdup(buf));
257             }
258 
259             if (SW->usetearlines && SW->edittearlines)
260             {
261                 make_tearline(buf);
262                 strcat(buf, "\n");
263                 ln = addline(ln, xstrdup(buf));
264             }
265 
266             if (SW->useoriginlines && SW->editoriginlines)
267             {
268                 /* add the origin line */
269 
270                 GetOrigin(buf2);
271                 sprintf(buf, " * Origin: %s (%s)\n", buf2,
272                         SW->domainorigin ? show_address(&(m->from)) :
273                         show_4d(&(m->from)));
274 
275                 ln = addline(ln, xstrdup(buf));
276             }
277         }
278     }
279 
280 
281     /* we've finished; assign it to the beginning of the msg */
282 
283     if (m->text == NULL && ln != NULL)
284     {
285         /* find beginning of msg and assign it */
286 
287         while (ln->prev)
288         {
289             ln = ln->prev;
290         }
291         m->text = ln;
292     }
293 
294     ln = m->text;
295     while (ln && ln->prev)
296     {
297         ln = ln->prev;
298     }
299     m->text = ln;
300 
301     release(monthbuf); release(wdaybuf);
302     release(use_month); release(use_day);
303 
304     return 0;
305 }
306 
addline(LINE * ln,char * l)307 static LINE* addline(LINE* ln,  char *l)
308 {
309     LINE *n;
310 
311     n = xcalloc(1, sizeof *n);
312 
313     n->templt = 1;  /* mark as a template line */
314 
315     if (ln)
316     {
317         n->next = ln->next;
318     }
319 
320     n->prev = ln;
321 
322     if (ln)
323     {
324         ln->next = n;
325     }
326 
327     if (n->next)
328     {
329         n->next->prev = n;
330     }
331 
332     n->text = l;
333     ln = n;
334 
335     return ln;
336 }
337 
338