2 * S-nail - 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
46 * Mail -- a mail program
60 struct macro
*ma_next
;
62 struct line
*ma_contents
;
69 static struct macro
*macros
[MAPRIME
];
70 static struct macro
*accounts
[MAPRIME
];
72 #define mahash(cp) (pjw(cp) % MAPRIME)
73 static void undef1(const char *name
, struct macro
**table
);
74 static int maexec(struct macro
*mp
);
75 static int closingangle(const char *cp
);
76 static struct macro
*malook(const char *name
, struct macro
*data
,
77 struct macro
**table
);
78 static void freelines(struct line
*lp
);
79 static void list0(FILE *fp
, struct line
*lp
);
80 static int list1(FILE *fp
, struct macro
**table
);
87 if (args
[0] == NULL
) {
88 fprintf(stderr
, "Missing macro name to define.\n");
91 if (args
[1] == NULL
|| strcmp(args
[1], "{") || args
[2] != NULL
) {
92 fprintf(stderr
, "Syntax is: define <name> {\n");
95 return define1(args
[0], 0);
99 define1(const char *name
, int account
)
102 struct line
*lp
, *lst
= NULL
, *lnd
= NULL
;
103 char *linebuf
= NULL
;
106 mp
= scalloc(1, sizeof *mp
);
107 mp
->ma_name
= sstrdup(name
);
109 mp
->ma_flags
|= MA_ACCOUNT
;
113 n
= readline_restart(input
, &linebuf
, &linesize
, n
);
116 if (n
== 0 || linebuf
[n
-1] != '\\')
121 fprintf(stderr
, "Unterminated %s definition: \"%s\".\n",
122 account
? "account" : "macro",
130 if (closingangle(linebuf
))
132 lp
= scalloc(1, sizeof *lp
);
133 lp
->l_linesize
= n
+1;
134 lp
->l_line
= smalloc(lp
->l_linesize
);
135 memcpy(lp
->l_line
, linebuf
, lp
->l_linesize
);
136 lp
->l_line
[n
] = '\0';
143 mp
->ma_contents
= lst
;
144 if (malook(mp
->ma_name
, mp
, account
? accounts
: macros
) != NULL
) {
147 "A macro named \"%s\" already exists.\n",
149 freelines(mp
->ma_contents
);
154 undef1(mp
->ma_name
, accounts
);
155 malook(mp
->ma_name
, mp
, accounts
);
166 fprintf(stderr
, "Missing macro name to undef.\n");
170 undef1(*args
, macros
);
176 undef1(const char *name
, struct macro
**table
)
180 if ((mp
= malook(name
, NULL
, table
)) != NULL
) {
181 freelines(mp
->ma_contents
);
193 if (args
[0] == NULL
|| (args
[1] != NULL
&& args
[2] != NULL
)) {
194 fprintf(stderr
, "Syntax is: call <name>\n");
197 if ((mp
= malook(*args
, NULL
, macros
)) == NULL
) {
198 fprintf(stderr
, "Undefined macro called: \"%s\"\n", *args
);
205 callaccount(const char *name
)
209 if ((mp
= malook(name
, NULL
, accounts
)) == NULL
)
215 callhook(const char *name
, int newmail
)
221 var
= ac_alloc(len
= strlen(name
) + 13);
222 snprintf(var
, len
, "folder-hook-%s", name
);
223 if ((cp
= value(var
)) == NULL
&& (cp
= value("folder-hook")) == NULL
)
225 if ((mp
= malook(cp
, NULL
, macros
)) == NULL
) {
226 fprintf(stderr
, "Cannot call hook for folder \"%s\": "
227 "Macro \"%s\" does not exist.\n",
231 inhook
= newmail
? 3 : 1;
238 maexec(struct macro
*mp
)
245 unset_allow_undefined
= 1;
246 for (lp
= mp
->ma_contents
; lp
; lp
= lp
->l_next
) {
248 while (sp
< &lp
->l_line
[lp
->l_linesize
] &&
249 (blankchar(*sp
&0377) || *sp
== '\n' ||
252 if (sp
== &lp
->l_line
[lp
->l_linesize
])
254 cp
= copy
= smalloc(lp
->l_linesize
+ (lp
->l_line
- sp
));
256 *cp
++ = *sp
!= '\n' ? *sp
: ' ';
257 while (++sp
< &lp
->l_line
[lp
->l_linesize
]);
258 r
= execute(copy
, 0, lp
->l_linesize
);
261 unset_allow_undefined
= 0;
266 closingangle(const char *cp
)
268 while (spacechar(*cp
&0377))
272 while (spacechar(*cp
&0377))
277 static struct macro
*
278 malook(const char *name
, struct macro
*data
, struct macro
**table
)
283 mp
= table
[h
= mahash(name
)];
285 if (mp
->ma_name
&& strcmp(mp
->ma_name
, name
) == 0)
292 data
->ma_next
= table
[h
];
299 freelines(struct line
*lp
)
301 struct line
*lq
= NULL
;
313 listaccounts(FILE *fp
)
315 return list1(fp
, accounts
);
319 list0(FILE *fp
, struct line
*lp
)
324 for (sp
= lp
->l_line
; sp
< &lp
->l_line
[lp
->l_linesize
]; sp
++) {
325 if ((c
= *sp
&0377) != '\0') {
326 if ((c
= *sp
&0377) == '\n')
335 list1(FILE *fp
, struct macro
**table
)
337 struct macro
**mp
, *mq
;
341 for (mp
= table
; mp
< &table
[MAPRIME
]; mp
++)
342 for (mq
= *mp
; mq
; mq
= mq
->ma_next
)
346 fprintf(fp
, "%s %s {\n",
348 "account" : "define",
350 for (lp
= mq
->ma_contents
; lp
; lp
= lp
->l_next
)
366 if ((fp
= Ftemp(&cp
, "Ra", "w+", 0600, 1)) == NULL
) {
372 mc
= list1(fp
, macros
);
380 delaccount(const char *name
)
382 undef1(name
, accounts
);