2 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
8 * Gunnar Ritter. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
41 static char sccsid
[] = "@(#)macro.c 1.13 (gritter) 3/4/06";
51 * Mail -- a mail program
65 struct macro
*ma_next
;
67 struct line
*ma_contents
;
74 static struct macro
*macros
[MAPRIME
];
75 static struct macro
*accounts
[MAPRIME
];
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
);
92 if (args
[0] == NULL
) {
93 fprintf(stderr
, "Missing macro name to define.\n");
96 if (args
[1] == NULL
|| strcmp(args
[1], "{") || args
[2] != NULL
) {
97 fprintf(stderr
, "Syntax is: define <name> {\n");
100 return define1(args
[0], 0);
104 define1(const char *name
, int account
)
107 struct line
*lp
, *lst
= NULL
, *lnd
= NULL
;
108 char *linebuf
= NULL
;
111 mp
= scalloc(1, sizeof *mp
);
112 mp
->ma_name
= sstrdup(name
);
114 mp
->ma_flags
|= MA_ACCOUNT
;
118 n
= readline_restart(input
, &linebuf
, &linesize
, n
);
121 if (n
== 0 || linebuf
[n
-1] != '\\')
126 fprintf(stderr
, "Unterminated %s definition: \"%s\".\n",
127 account
? "account" : "macro",
135 if (closingangle(linebuf
))
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';
148 mp
->ma_contents
= lst
;
149 if (malook(mp
->ma_name
, mp
, account
? accounts
: macros
) != NULL
) {
152 "A macro named \"%s\" already exists.\n",
154 freelines(mp
->ma_contents
);
159 undef1(mp
->ma_name
, accounts
);
160 malook(mp
->ma_name
, mp
, accounts
);
171 fprintf(stderr
, "Missing macro name to undef.\n");
175 undef1(*args
, macros
);
181 undef1(const char *name
, struct macro
**table
)
185 if ((mp
= malook(name
, NULL
, table
)) != NULL
) {
186 freelines(mp
->ma_contents
);
198 if (args
[0] == NULL
|| args
[1] != NULL
&& args
[2] != NULL
) {
199 fprintf(stderr
, "Syntax is: call <name>\n");
202 if ((mp
= malook(*args
, NULL
, macros
)) == NULL
) {
203 fprintf(stderr
, "Undefined macro called: \"%s\"\n", *args
);
210 callaccount(const char *name
)
214 if ((mp
= malook(name
, NULL
, accounts
)) == NULL
)
220 callhook(const char *name
, int newmail
)
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
)
230 if ((mp
= malook(cp
, NULL
, macros
)) == NULL
) {
231 fprintf(stderr
, "Cannot call hook for folder \"%s\": "
232 "Macro \"%s\" does not exist.\n",
236 inhook
= newmail
? 3 : 1;
243 maexec(struct macro
*mp
)
250 unset_allow_undefined
= 1;
251 for (lp
= mp
->ma_contents
; lp
; lp
= lp
->l_next
) {
253 while (sp
< &lp
->l_line
[lp
->l_linesize
] &&
254 (blankchar(*sp
&0377) || *sp
== '\n' ||
257 if (sp
== &lp
->l_line
[lp
->l_linesize
])
259 cp
= copy
= smalloc(lp
->l_linesize
+ (lp
->l_line
- sp
));
261 *cp
++ = *sp
!= '\n' ? *sp
: ' ';
262 while (++sp
< &lp
->l_line
[lp
->l_linesize
]);
263 r
= execute(copy
, 0, lp
->l_linesize
);
266 unset_allow_undefined
= 0;
271 closingangle(const char *cp
)
273 while (spacechar(*cp
&0377))
277 while (spacechar(*cp
&0377))
282 static struct macro
*
283 malook(const char *name
, struct macro
*data
, struct macro
**table
)
288 mp
= table
[h
= mahash(name
)];
290 if (mp
->ma_name
&& strcmp(mp
->ma_name
, name
) == 0)
297 data
->ma_next
= table
[h
];
304 freelines(struct line
*lp
)
306 struct line
*lq
= NULL
;
318 listaccounts(FILE *fp
)
320 return list1(fp
, accounts
);
324 list0(FILE *fp
, struct line
*lp
)
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')
340 list1(FILE *fp
, struct macro
**table
)
342 struct macro
**mp
, *mq
;
346 for (mp
= table
; mp
< &table
[MAPRIME
]; mp
++)
347 for (mq
= *mp
; mq
; mq
= mq
->ma_next
)
351 fprintf(fp
, "%s %s {\n",
353 "account" : "define",
355 for (lp
= mq
->ma_contents
; lp
; lp
= lp
->l_next
)
370 if ((fp
= Ftemp(&cp
, "Ra", "w+", 0600, 1)) == NULL
) {
376 mc
= list1(fp
, macros
);
384 delaccount(const char *name
)
386 undef1(name
, accounts
);