2 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 Steffen "Daode" Nurpmeso.
9 * Gunnar Ritter. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Gunnar Ritter
22 * and his contributors.
23 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 static char sccsid
[] = "@(#)macro.c 1.13 (gritter) 3/4/06";
52 * Mail -- a mail program
66 struct macro
*ma_next
;
68 struct line
*ma_contents
;
75 static struct macro
*macros
[MAPRIME
];
76 static struct macro
*accounts
[MAPRIME
];
78 #define mahash(cp) (pjw(cp) % MAPRIME)
79 static void undef1(const char *name
, struct macro
**table
);
80 static int maexec(struct macro
*mp
);
81 static int closingangle(const char *cp
);
82 static struct macro
*malook(const char *name
, struct macro
*data
,
83 struct macro
**table
);
84 static void freelines(struct line
*lp
);
85 static void list0(FILE *fp
, struct line
*lp
);
86 static int list1(FILE *fp
, struct macro
**table
);
93 if (args
[0] == NULL
) {
94 fprintf(stderr
, "Missing macro name to define.\n");
97 if (args
[1] == NULL
|| strcmp(args
[1], "{") || args
[2] != NULL
) {
98 fprintf(stderr
, "Syntax is: define <name> {\n");
101 return define1(args
[0], 0);
105 define1(const char *name
, int account
)
108 struct line
*lp
, *lst
= NULL
, *lnd
= NULL
;
109 char *linebuf
= NULL
;
112 mp
= scalloc(1, sizeof *mp
);
113 mp
->ma_name
= sstrdup(name
);
115 mp
->ma_flags
|= MA_ACCOUNT
;
119 n
= readline_restart(input
, &linebuf
, &linesize
, n
);
122 if (n
== 0 || linebuf
[n
-1] != '\\')
127 fprintf(stderr
, "Unterminated %s definition: \"%s\".\n",
128 account
? "account" : "macro",
136 if (closingangle(linebuf
))
138 lp
= scalloc(1, sizeof *lp
);
139 lp
->l_linesize
= n
+1;
140 lp
->l_line
= smalloc(lp
->l_linesize
);
141 memcpy(lp
->l_line
, linebuf
, lp
->l_linesize
);
142 lp
->l_line
[n
] = '\0';
149 mp
->ma_contents
= lst
;
150 if (malook(mp
->ma_name
, mp
, account
? accounts
: macros
) != NULL
) {
153 "A macro named \"%s\" already exists.\n",
155 freelines(mp
->ma_contents
);
160 undef1(mp
->ma_name
, accounts
);
161 malook(mp
->ma_name
, mp
, accounts
);
172 fprintf(stderr
, "Missing macro name to undef.\n");
176 undef1(*args
, macros
);
182 undef1(const char *name
, struct macro
**table
)
186 if ((mp
= malook(name
, NULL
, table
)) != NULL
) {
187 freelines(mp
->ma_contents
);
199 if (args
[0] == NULL
|| (args
[1] != NULL
&& args
[2] != NULL
)) {
200 fprintf(stderr
, "Syntax is: call <name>\n");
203 if ((mp
= malook(*args
, NULL
, macros
)) == NULL
) {
204 fprintf(stderr
, "Undefined macro called: \"%s\"\n", *args
);
211 callaccount(const char *name
)
215 if ((mp
= malook(name
, NULL
, accounts
)) == NULL
)
221 callhook(const char *name
, int newmail
)
227 var
= ac_alloc(len
= strlen(name
) + 13);
228 snprintf(var
, len
, "folder-hook-%s", name
);
229 if ((cp
= value(var
)) == NULL
&& (cp
= value("folder-hook")) == NULL
)
231 if ((mp
= malook(cp
, NULL
, macros
)) == NULL
) {
232 fprintf(stderr
, "Cannot call hook for folder \"%s\": "
233 "Macro \"%s\" does not exist.\n",
237 inhook
= newmail
? 3 : 1;
244 maexec(struct macro
*mp
)
251 unset_allow_undefined
= 1;
252 for (lp
= mp
->ma_contents
; lp
; lp
= lp
->l_next
) {
254 while (sp
< &lp
->l_line
[lp
->l_linesize
] &&
255 (blankchar(*sp
&0377) || *sp
== '\n' ||
258 if (sp
== &lp
->l_line
[lp
->l_linesize
])
260 cp
= copy
= smalloc(lp
->l_linesize
+ (lp
->l_line
- sp
));
262 *cp
++ = *sp
!= '\n' ? *sp
: ' ';
263 while (++sp
< &lp
->l_line
[lp
->l_linesize
]);
264 r
= execute(copy
, 0, lp
->l_linesize
);
267 unset_allow_undefined
= 0;
272 closingangle(const char *cp
)
274 while (spacechar(*cp
&0377))
278 while (spacechar(*cp
&0377))
283 static struct macro
*
284 malook(const char *name
, struct macro
*data
, struct macro
**table
)
289 mp
= table
[h
= mahash(name
)];
291 if (mp
->ma_name
&& strcmp(mp
->ma_name
, name
) == 0)
298 data
->ma_next
= table
[h
];
305 freelines(struct line
*lp
)
307 struct line
*lq
= NULL
;
319 listaccounts(FILE *fp
)
321 return list1(fp
, accounts
);
325 list0(FILE *fp
, struct line
*lp
)
330 for (sp
= lp
->l_line
; sp
< &lp
->l_line
[lp
->l_linesize
]; sp
++) {
331 if ((c
= *sp
&0377) != '\0') {
332 if ((c
= *sp
&0377) == '\n')
341 list1(FILE *fp
, struct macro
**table
)
343 struct macro
**mp
, *mq
;
347 for (mp
= table
; mp
< &table
[MAPRIME
]; mp
++)
348 for (mq
= *mp
; mq
; mq
= mq
->ma_next
)
352 fprintf(fp
, "%s %s {\n",
354 "account" : "define",
356 for (lp
= mq
->ma_contents
; lp
; lp
= lp
->l_next
)
372 if ((fp
= Ftemp(&cp
, "Ra", "w+", 0600, 1)) == NULL
) {
378 mc
= list1(fp
, macros
);
386 delaccount(const char *name
)
388 undef1(name
, accounts
);