~ubuntu-branches/ubuntu/oneiric/heirloom-mailx/oneiric

« back to all changes in this revision

Viewing changes to macro.c

  • Committer: Bazaar Package Importer
  • Author(s): Hilko Bengen
  • Date: 2008-02-18 20:45:00 UTC
  • Revision ID: james.westby@ubuntu.com-20080218204500-ezficstzczzr7v19
Tags: upstream-12.3
ImportĀ upstreamĀ versionĀ 12.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
 
3
 *
 
4
 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
 
5
 */
 
6
/*
 
7
 * Copyright (c) 2004
 
8
 *      Gunnar Ritter.  All rights reserved.
 
9
 *
 
10
 * Redistribution and use in source and binary forms, with or without
 
11
 * modification, are permitted provided that the following conditions
 
12
 * are met:
 
13
 * 1. Redistributions of source code must retain the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer.
 
15
 * 2. Redistributions in binary form must reproduce the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer in the
 
17
 *    documentation and/or other materials provided with the distribution.
 
18
 * 3. All advertising materials mentioning features or use of this software
 
19
 *    must display the following acknowledgement:
 
20
 *      This product includes software developed by Gunnar Ritter
 
21
 *      and his contributors.
 
22
 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
 
23
 *    may be used to endorse or promote products derived from this software
 
24
 *    without specific prior written permission.
 
25
 *
 
26
 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
 
27
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
29
 * ARE DISCLAIMED.  IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
 
30
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
31
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
32
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
33
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
34
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
35
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
36
 * SUCH DAMAGE.
 
37
 */
 
38
 
 
39
#ifndef lint
 
40
#ifdef  DOSCCS
 
41
static char sccsid[] = "@(#)macro.c     1.13 (gritter) 3/4/06";
 
42
#endif
 
43
#endif /* not lint */
 
44
 
 
45
#include "config.h"
 
46
 
 
47
#include "rcv.h"
 
48
#include "extern.h"
 
49
 
 
50
/*
 
51
 * Mail -- a mail program
 
52
 *
 
53
 * Macros.
 
54
 */
 
55
 
 
56
#define MAPRIME         29
 
57
 
 
58
struct line {
 
59
        struct line     *l_next;
 
60
        char    *l_line;
 
61
        size_t  l_linesize;
 
62
};
 
63
 
 
64
struct macro {
 
65
        struct macro    *ma_next;
 
66
        char    *ma_name;
 
67
        struct line     *ma_contents;
 
68
        enum maflags {
 
69
                MA_NOFLAGS,
 
70
                MA_ACCOUNT
 
71
        } ma_flags;
 
72
};
 
73
 
 
74
static struct macro     *macros[MAPRIME];
 
75
static struct macro     *accounts[MAPRIME];
 
76
 
 
77
#define mahash(cp)      (pjw(cp) % MAPRIME)
 
78
static void undef1(const char *name, struct macro **table);
 
79
static int maexec(struct macro *mp);
 
80
static int closingangle(const char *cp);
 
81
static struct macro *malook(const char *name, struct macro *data,
 
82
                struct macro **table);
 
83
static void freelines(struct line *lp);
 
84
static void list0(FILE *fp, struct line *lp);
 
85
static int list1(FILE *fp, struct macro **table);
 
86
 
 
87
int 
 
88
cdefine(void *v)
 
89
{
 
90
        char    **args = v;
 
91
 
 
92
        if (args[0] == NULL) {
 
93
                fprintf(stderr, "Missing macro name to define.\n");
 
94
                return 1;
 
95
        }
 
96
        if (args[1] == NULL || strcmp(args[1], "{") || args[2] != NULL) {
 
97
                fprintf(stderr, "Syntax is: define <name> {\n");
 
98
                return 1;
 
99
        }
 
100
        return define1(args[0], 0);
 
101
}
 
102
 
 
103
int 
 
104
define1(const char *name, int account)
 
105
{
 
106
        struct macro    *mp;
 
107
        struct line     *lp, *lst = NULL, *lnd = NULL;
 
108
        char    *linebuf = NULL;
 
109
        size_t  linesize = 0;
 
110
        int     n;
 
111
        mp = scalloc(1, sizeof *mp);
 
112
        mp->ma_name = sstrdup(name);
 
113
        if (account)
 
114
                mp->ma_flags |= MA_ACCOUNT;
 
115
        for (;;) {
 
116
                n = 0;
 
117
                for (;;) {
 
118
                        n = readline_restart(input, &linebuf, &linesize, n);
 
119
                        if (n < 0)
 
120
                                break;
 
121
                        if (n == 0 || linebuf[n-1] != '\\')
 
122
                                break;
 
123
                        linebuf[n-1] = '\n';
 
124
                }
 
125
                if (n < 0) {
 
126
                        fprintf(stderr, "Unterminated %s definition: \"%s\".\n",
 
127
                                        account ? "account" : "macro",
 
128
                                        mp->ma_name);
 
129
                        if (sourcing)
 
130
                                unstack();
 
131
                        free(mp->ma_name);
 
132
                        free(mp);
 
133
                        return 1;
 
134
                }
 
135
                if (closingangle(linebuf))
 
136
                        break;
 
137
                lp = scalloc(1, sizeof *lp);
 
138
                lp->l_linesize = n+1;
 
139
                lp->l_line = smalloc(lp->l_linesize);
 
140
                memcpy(lp->l_line, linebuf, lp->l_linesize);
 
141
                lp->l_line[n] = '\0';
 
142
                if (lst && lnd) {
 
143
                        lnd->l_next = lp;
 
144
                        lnd = lp;
 
145
                } else
 
146
                        lst = lnd = lp;
 
147
        }
 
148
        mp->ma_contents = lst;
 
149
        if (malook(mp->ma_name, mp, account ? accounts : macros) != NULL) {
 
150
                if (!account) {
 
151
                        fprintf(stderr,
 
152
                                "A macro named \"%s\" already exists.\n",
 
153
                                mp->ma_name);
 
154
                        freelines(mp->ma_contents);
 
155
                        free(mp->ma_name);
 
156
                        free(mp);
 
157
                        return 1;
 
158
                }
 
159
                undef1(mp->ma_name, accounts);
 
160
                malook(mp->ma_name, mp, accounts);
 
161
        }
 
162
        return 0;
 
163
}
 
164
 
 
165
int 
 
166
cundef(void *v)
 
167
{
 
168
        char    **args = v;
 
169
 
 
170
        if (*args == NULL) {
 
171
                fprintf(stderr, "Missing macro name to undef.\n");
 
172
                return 1;
 
173
        }
 
174
        do
 
175
                undef1(*args, macros);
 
176
        while (*++args);
 
177
        return 0;
 
178
}
 
179
 
 
180
static void 
 
181
undef1(const char *name, struct macro **table)
 
182
{
 
183
        struct macro    *mp;
 
184
 
 
185
        if ((mp = malook(name, NULL, table)) != NULL) {
 
186
                freelines(mp->ma_contents);
 
187
                free(mp->ma_name);
 
188
                mp->ma_name = NULL;
 
189
        }
 
190
}
 
191
 
 
192
int 
 
193
ccall(void *v)
 
194
{
 
195
        char    **args = v;
 
196
        struct macro    *mp;
 
197
 
 
198
        if (args[0] == NULL || args[1] != NULL && args[2] != NULL) {
 
199
                fprintf(stderr, "Syntax is: call <name>\n");
 
200
                return 1;
 
201
        }
 
202
        if ((mp = malook(*args, NULL, macros)) == NULL) {
 
203
                fprintf(stderr, "Undefined macro called: \"%s\"\n", *args);
 
204
                return 1;
 
205
        }
 
206
        return maexec(mp);
 
207
}
 
208
 
 
209
int 
 
210
callaccount(const char *name)
 
211
{
 
212
        struct macro    *mp;
 
213
 
 
214
        if ((mp = malook(name, NULL, accounts)) == NULL)
 
215
                return CBAD;
 
216
        return maexec(mp);
 
217
}
 
218
 
 
219
int 
 
220
callhook(const char *name, int newmail)
 
221
{
 
222
        struct macro    *mp;
 
223
        char    *var, *cp;
 
224
        int     len, r;
 
225
 
 
226
        var = ac_alloc(len = strlen(name) + 13);
 
227
        snprintf(var, len, "folder-hook-%s", name);
 
228
        if ((cp = value(var)) == NULL && (cp = value("folder-hook")) == NULL)
 
229
                return 0;
 
230
        if ((mp = malook(cp, NULL, macros)) == NULL) {
 
231
                fprintf(stderr, "Cannot call hook for folder \"%s\": "
 
232
                                "Macro \"%s\" does not exist.\n",
 
233
                                name, cp);
 
234
                return 1;
 
235
        }
 
236
        inhook = newmail ? 3 : 1;
 
237
        r = maexec(mp);
 
238
        inhook = 0;
 
239
        return r;
 
240
}
 
241
 
 
242
static int 
 
243
maexec(struct macro *mp)
 
244
{
 
245
        struct line     *lp;
 
246
        const char      *sp;
 
247
        char    *copy, *cp;
 
248
        int     r = 0;
 
249
 
 
250
        unset_allow_undefined = 1;
 
251
        for (lp = mp->ma_contents; lp; lp = lp->l_next) {
 
252
                sp = lp->l_line;
 
253
                while (sp < &lp->l_line[lp->l_linesize] &&
 
254
                                (blankchar(*sp&0377) || *sp == '\n' ||
 
255
                                 *sp == '\0'))
 
256
                        sp++;
 
257
                if (sp == &lp->l_line[lp->l_linesize])
 
258
                        continue;
 
259
                cp = copy = smalloc(lp->l_linesize + (lp->l_line - sp));
 
260
                do
 
261
                        *cp++ = *sp != '\n' ? *sp : ' ';
 
262
                while (++sp < &lp->l_line[lp->l_linesize]);
 
263
                r = execute(copy, 0, lp->l_linesize);
 
264
                free(copy);
 
265
        }
 
266
        unset_allow_undefined = 0;
 
267
        return r;
 
268
}
 
269
 
 
270
static int 
 
271
closingangle(const char *cp)
 
272
{
 
273
        while (spacechar(*cp&0377))
 
274
                cp++;
 
275
        if (*cp++ != '}')
 
276
                return 0;
 
277
        while (spacechar(*cp&0377))
 
278
                cp++;
 
279
        return *cp == '\0';
 
280
}
 
281
 
 
282
static struct macro *
 
283
malook(const char *name, struct macro *data, struct macro **table)
 
284
{
 
285
        struct macro    *mp;
 
286
        unsigned        h;
 
287
 
 
288
        mp = table[h = mahash(name)];
 
289
        while (mp != NULL) {
 
290
                if (mp->ma_name && strcmp(mp->ma_name, name) == 0)
 
291
                        break;
 
292
                mp = mp->ma_next;
 
293
        }
 
294
        if (data) {
 
295
                if (mp != NULL)
 
296
                        return mp;
 
297
                data->ma_next = table[h];
 
298
                table[h] = data;
 
299
        }
 
300
        return mp;
 
301
}
 
302
 
 
303
static void 
 
304
freelines(struct line *lp)
 
305
{
 
306
        struct line     *lq = NULL;
 
307
 
 
308
        while (lp) {
 
309
                free(lp->l_line);
 
310
                free(lq);
 
311
                lq = lp;
 
312
                lp = lp->l_next;
 
313
        }
 
314
        free(lq);
 
315
}
 
316
 
 
317
int
 
318
listaccounts(FILE *fp)
 
319
{
 
320
        return list1(fp, accounts);
 
321
}
 
322
 
 
323
static void
 
324
list0(FILE *fp, struct line *lp)
 
325
{
 
326
        const char      *sp;
 
327
        int     c;
 
328
 
 
329
        for (sp = lp->l_line; sp < &lp->l_line[lp->l_linesize]; sp++) {
 
330
                if ((c = *sp&0377) != '\0') {
 
331
                        if ((c = *sp&0377) == '\n')
 
332
                                putc('\\', fp);
 
333
                        putc(c, fp);
 
334
                }
 
335
        }
 
336
        putc('\n', fp);
 
337
}
 
338
 
 
339
static int
 
340
list1(FILE *fp, struct macro **table)
 
341
{
 
342
        struct macro    **mp, *mq;
 
343
        struct line     *lp;
 
344
        int     mc = 0;
 
345
 
 
346
        for (mp = table; mp < &table[MAPRIME]; mp++)
 
347
                for (mq = *mp; mq; mq = mq->ma_next)
 
348
                        if (mq->ma_name) {
 
349
                                if (mc++)
 
350
                                        fputc('\n', fp);
 
351
                                fprintf(fp, "%s %s {\n",
 
352
                                                table == accounts ?
 
353
                                                        "account" : "define",
 
354
                                                mq->ma_name);
 
355
                                for (lp = mq->ma_contents; lp; lp = lp->l_next)
 
356
                                        list0(fp, lp);
 
357
                                fputs("}\n", fp);
 
358
                        }
 
359
        return mc;
 
360
}
 
361
 
 
362
/*ARGSUSED*/
 
363
int 
 
364
cdefines(void *v)
 
365
{
 
366
        FILE    *fp;
 
367
        char    *cp;
 
368
        int     mc;
 
369
 
 
370
        if ((fp = Ftemp(&cp, "Ra", "w+", 0600, 1)) == NULL) {
 
371
                perror("tmpfile");
 
372
                return 1;
 
373
        }
 
374
        rm(cp);
 
375
        Ftfree(&cp);
 
376
        mc = list1(fp, macros);
 
377
        if (mc)
 
378
                try_pager(fp);
 
379
        Fclose(fp);
 
380
        return 0;
 
381
}
 
382
 
 
383
void 
 
384
delaccount(const char *name)
 
385
{
 
386
        undef1(name, accounts);
 
387
}