Add ~I command escape (like ~i, but do not add newline)
[s-mailx.git] / cmd-resend.c
blob96c0d91eaa2ef7da20048b93b4109500c835229f
1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ All sorts of `reply', `resend', `forward', and similar user commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
6 */
7 /*
8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
35 #undef n_FILE
36 #define n_FILE cmd_resend
38 #ifndef HAVE_AMALGAMATION
39 # include "nail.h"
40 #endif
42 /* Modify subject we reply to to begin with Re: if it does not already */
43 static char *a_crese_reedit(char const *subj);
45 static void make_ref_and_cs(struct message *mp, struct header *head);
47 /* `reply' and `Lreply' workhorse */
48 static int a_crese_list_reply(int *msgvec, enum header_flags hf);
50 /* Get PTF to implementation of command c (i.e., take care for *flipr*) */
51 static int (* _reply_or_Reply(char c))(int *, bool_t);
53 /* Reply to a single message. Extract each name from the message header and
54 * send them off to mail1() */
55 static int _reply(int *msgvec, bool_t recipient_record);
57 /* Reply to a series of messages by simply mailing to the senders and not
58 * messing around with the To: and Cc: lists as in normal reply */
59 static int _Reply(int *msgvec, bool_t recipient_record);
61 /* Forward a message to a new recipient, in the sense of RFC 2822 */
62 static int _fwd(char *str, int recipient_record);
64 /* Modify the subject we are replying to to begin with Fwd: */
65 static char * __fwdedit(char *subj);
67 /* Do the real work of resending */
68 static int _resend1(void *v, bool_t add_resent);
70 static char *
71 a_crese_reedit(char const *subj){
72 char *newsubj;
73 NYD_ENTER;
75 newsubj = NULL;
77 if(subj != NULL && *subj != '\0'){
78 struct str in, out;
79 size_t i;
80 char const *cp;
82 in.l = strlen(in.s = n_UNCONST(subj));
83 mime_fromhdr(&in, &out, TD_ISPR | TD_ICONV);
85 i = strlen(cp = subject_re_trim(out.s)) +1;
86 /* RFC mandates english "Re: " */
87 newsubj = salloc(sizeof("Re: ") -1 + i);
88 memcpy(newsubj, "Re: ", sizeof("Re: ") -1);
89 memcpy(&newsubj[sizeof("Re: ") -1], cp, i);
91 free(out.s);
93 NYD_LEAVE;
94 return newsubj;
97 static void
98 make_ref_and_cs(struct message *mp, struct header *head) /* TODO rewrite FAST */
100 char *oldref, *oldmsgid, *newref, *cp;
101 size_t oldreflen = 0, oldmsgidlen = 0, reflen;
102 unsigned i;
103 struct name *n;
104 NYD_ENTER;
106 oldref = hfield1("references", mp);
107 oldmsgid = hfield1("message-id", mp);
108 if (oldmsgid == NULL || *oldmsgid == '\0') {
109 head->h_ref = NULL;
110 goto jleave;
113 reflen = 1;
114 if (oldref) {
115 oldreflen = strlen(oldref);
116 reflen += oldreflen + 2;
118 if (oldmsgid) {
119 oldmsgidlen = strlen(oldmsgid);
120 reflen += oldmsgidlen;
123 newref = smalloc(reflen);
124 if (oldref != NULL) {
125 memcpy(newref, oldref, oldreflen +1);
126 if (oldmsgid != NULL) {
127 newref[oldreflen++] = ',';
128 newref[oldreflen++] = ' ';
129 memcpy(newref + oldreflen, oldmsgid, oldmsgidlen +1);
131 } else if (oldmsgid)
132 memcpy(newref, oldmsgid, oldmsgidlen +1);
133 n = extract(newref, GREF);
134 free(newref);
136 /* Limit number of references TODO better on parser side */
137 while (n->n_flink != NULL)
138 n = n->n_flink;
139 for (i = 1; i <= REFERENCES_MAX; ++i) {
140 if (n->n_blink != NULL)
141 n = n->n_blink;
142 else
143 break;
145 n->n_blink = NULL;
146 head->h_ref = n;
147 if (ok_blook(reply_in_same_charset) &&
148 (cp = hfield1("content-type", mp)) != NULL){
149 if((head->h_charset = cp = mime_param_get("charset", cp)) != NULL){
150 char *cpo, c;
152 for(cpo = cp; (c = *cpo) != '\0'; ++cpo)
153 *cpo = lowerconv(c);
155 head->h_charset = n_charsetalias_expand(cp);
158 jleave:
159 NYD_LEAVE;
162 static int
163 a_crese_list_reply(int *msgvec, enum header_flags hf)
165 struct header head;
166 struct message *mp;
167 char const *reply_to, *rcv, *cp;
168 enum gfield gf;
169 struct name *rt, *mft, *np;
170 int *save_msgvec;
171 NYD_ENTER;
173 /* TODO Since we may recur and do stuff with message lists we need to save
174 * TODO away the argument vector as long as that isn't done by machinery */
176 size_t i;
177 for (i = 0; msgvec[i] != 0; ++i)
179 ++i;
180 save_msgvec = ac_alloc(sizeof(*save_msgvec) * i);
181 while (i-- > 0)
182 save_msgvec[i] = msgvec[i];
183 msgvec = save_msgvec;
186 gf = ok_blook(fullnames) ? GFULL | GSKIN : GSKIN;
188 jnext_msg:
189 n_autorec_relax_create();
190 mp = &message[*msgvec - 1];
191 touch(mp);
192 setdot(mp);
194 memset(&head, 0, sizeof head);
195 head.h_flags = hf;
196 head.h_subject = a_crese_reedit(hfield1("subject", mp));
197 head.h_mailx_command = "reply";
198 head.h_mailx_orig_from = lextract(hfield1("from", mp), GIDENT | gf);
199 head.h_mailx_orig_to = lextract(hfield1("to", mp), GTO | gf);
200 head.h_mailx_orig_cc = lextract(hfield1("cc", mp), GCC | gf);
201 head.h_mailx_orig_bcc = lextract(hfield1("bcc", mp), GBCC | gf);
202 rt = mft = NULL;
204 rcv = NULL;
205 if ((reply_to = hfield1("reply-to", mp)) != NULL &&
206 (cp = ok_vlook(reply_to_honour)) != NULL &&
207 (rt = checkaddrs(lextract(reply_to, GTO | gf), EACM_STRICT, NULL)
208 ) != NULL) {
209 char *sp;
210 size_t l;
211 char const *tr;
213 tr = _("Reply-To %s%s");
214 l = strlen(tr) + strlen(rt->n_name) + 3 +1;
215 sp = n_autorec_alloc(l);
216 snprintf(sp, l, tr, rt->n_name, (rt->n_flink != NULL ? "..." : n_empty));
218 if(quadify(cp, UIZ_MAX, sp, TRU1) > FAL0)
219 rcv = reply_to;
222 if (rcv == NULL && (rcv = hfield1("from", mp)) == NULL)
223 rcv = nameof(mp, 1);
225 /* Cc: */
226 np = NULL;
227 if (ok_blook(recipients_in_cc) && (cp = hfield1("to", mp)) != NULL)
228 np = lextract(cp, GCC | gf);
229 if ((cp = hfield1("cc", mp)) != NULL) {
230 struct name *x;
232 if((x = lextract(cp, GCC | gf)) != NULL)
233 np = cat(np, x);
235 if (np != NULL) {
236 head.h_mailx_raw_cc = namelist_dup(np, GCC | gf);
237 head.h_cc = n_alternates_remove(np, FAL0);
240 /* To: */
241 np = NULL;
242 if (rcv != NULL)
243 np = (rcv == reply_to) ? namelist_dup(rt, GTO | gf)
244 : lextract(rcv, GTO | gf);
245 if (!ok_blook(recipients_in_cc) && (cp = hfield1("to", mp)) != NULL) {
246 struct name *x;
248 if((x = lextract(cp, GTO | gf)) != NULL)
249 np = cat(np, x);
251 /* Delete my name from reply list, and with it, all my alternate names */
252 if(np != NULL){
253 head.h_mailx_raw_to = namelist_dup(np, GTO | gf);
254 np = n_alternates_remove(np, FAL0);
255 if(count(np) == 0){
256 np = lextract(rcv, GTO | gf);
257 head.h_mailx_raw_to = namelist_dup(np, GTO | gf);
260 head.h_to = np;
262 /* The user may have send this to himself, don't ignore that */
263 namelist_vaporise_head(&head, EACM_NORMAL, FAL0, NULL);
264 if (head.h_to == NULL)
265 head.h_to = np;
267 /* Mail-Followup-To: */
268 mft = NULL;
269 if (ok_vlook(followup_to_honour) != NULL &&
270 (cp = hfield1("mail-followup-to", mp)) != NULL &&
271 (mft = np = checkaddrs(lextract(cp, GTO | gf), EACM_STRICT, NULL)
272 ) != NULL) {
273 char *sp;
274 size_t l;
275 char const *tr;
277 tr = _("Followup-To %s%s");
278 l = strlen(tr) + strlen(np->n_name) + 3 +1;
279 sp = n_autorec_alloc(l);
280 snprintf(sp, l, tr, np->n_name, (np->n_flink != NULL ? "..." : n_empty));
282 if(quadify(ok_vlook(followup_to_honour), UIZ_MAX, sp, TRU1) > FAL0){
283 head.h_cc = NULL;
284 head.h_to = np;
285 head.h_mft =
286 mft = namelist_vaporise_head(&head, EACM_STRICT, FAL0, NULL);
287 }else
288 mft = NULL;
291 /* Special massage for list (follow-up) messages */
292 if (mft != NULL || (hf & HF_LIST_REPLY) || ok_blook(followup_to)) {
293 /* Learn about a possibly sending mailing list; use do for break; */
294 if ((cp = hfield1("list-post", mp)) != NULL) do {
295 struct name *x;
297 if ((x = lextract(cp, GEXTRA | GSKIN)) == NULL || x->n_flink != NULL ||
298 (cp = url_mailto_to_address(x->n_name)) == NULL ||
299 /* XXX terribly wasteful to create a new name, and can't we find
300 * XXX a way to mitigate that?? */
301 is_addr_invalid(x = nalloc(cp, GEXTRA | GSKIN), EACM_STRICT)) {
302 if(n_poption & n_PO_D_V)
303 n_err(_("Message contains invalid List-Post: header\n"));
304 cp = NULL;
305 break;
307 cp = x->n_name;
309 /* A special case has been seen on e.g. ietf-announce@ietf.org:
310 * these usually post to multiple groups, with ietf-announce@
311 * in List-Post:, but with Reply-To: set to ietf@ietf.org (since
312 * -announce@ is only used for announcements, say).
313 * So our desire is to honour this request and actively overwrite
314 * List-Post: for our purpose; but only if its a single address.
315 * However, to avoid ambiguities with users that place themselve in
316 * Reply-To: and mailing lists which don't overwrite this (or only
317 * extend this, shall such exist), only do so if reply_to exists of
318 * a single address which points to the same domain as List-Post: */
319 if (rt != NULL && rt->n_flink == NULL &&
320 name_is_same_domain(x, rt))
321 cp = rt->n_name; /* rt is EACM_STRICT tested */
323 /* "Automatically `mlist'" the List-Post: address temporarily */
324 if (is_mlist(cp, FAL0) == MLIST_OTHER)
325 head.h_list_post = cp;
326 else
327 cp = NULL;
328 } while (0);
330 /* In case of list replies we actively sort out any non-list recipient,
331 * but _only_ if we did not honour a MFT:, assuming that members of MFT
332 * were there for a reason; cp is still List-Post:/eqivalent */
333 if ((hf & HF_LIST_REPLY) && mft == NULL) {
334 struct name *nhp = head.h_to;
335 head.h_to = NULL;
336 j_lt_redo:
337 while (nhp != NULL) {
338 np = nhp;
339 nhp = nhp->n_flink;
341 if ((cp != NULL && !asccasecmp(cp, np->n_name)) ||
342 is_mlist(np->n_name, FAL0) != MLIST_OTHER) {
343 np->n_type = (np->n_type & ~GMASK) | GTO;
344 np->n_flink = head.h_to;
345 head.h_to = np;
348 if ((nhp = head.h_cc) != NULL) {
349 head.h_cc = NULL;
350 goto j_lt_redo;
355 make_ref_and_cs(mp, &head);
357 if (ok_blook(quote_as_attachment)) {
358 head.h_attach = csalloc(1, sizeof *head.h_attach);
359 head.h_attach->a_msgno = *msgvec;
360 head.h_attach->a_content_description = _("Original message content");
363 if (mail1(&head, 1, mp, NULL, !!(hf & HF_RECIPIENT_RECORD), 0) != OKAY) {
364 msgvec = NULL;
365 goto jleave;
367 if(ok_blook(markanswered) && !(mp->m_flag & MANSWERED))
368 mp->m_flag |= MANSWER | MANSWERED;
369 n_autorec_relax_gut();
371 if (*++msgvec != 0) {
372 /* TODO message (error) ring.., less sleep */
373 if(n_psonce & n_PSO_INTERACTIVE){
374 fprintf(n_stdout,
375 _("Waiting a second before proceeding to the next message..\n"));
376 fflush(n_stdout);
377 n_msleep(1000, FAL0);
379 goto jnext_msg;
382 jleave:
383 ac_free(save_msgvec);
384 NYD_LEAVE;
385 return (msgvec == NULL);
388 static int
389 (*_reply_or_Reply(char c))(int *, bool_t)
391 int (*rv)(int*, bool_t);
392 NYD_ENTER;
394 rv = (ok_blook(flipr) ^ (c == 'R')) ? &_Reply : &_reply;
395 NYD_LEAVE;
396 return rv;
399 static int
400 _reply(int *msgvec, bool_t recipient_record)
402 int rv;
403 NYD_ENTER;
405 rv = a_crese_list_reply(msgvec,
406 (recipient_record ? HF_RECIPIENT_RECORD : HF_NONE));
407 NYD_LEAVE;
408 return rv;
411 static int
412 _Reply(int *msgvec, bool_t recipient_record)
414 struct header head;
415 struct message *mp;
416 int *ap;
417 char *cp;
418 enum gfield gf;
419 NYD_ENTER;
421 memset(&head, 0, sizeof head);
422 gf = ok_blook(fullnames) ? GFULL | GSKIN : GSKIN;
424 for (ap = msgvec; *ap != 0; ++ap) {
425 char const *rp;
426 struct name *rt;
428 mp = &message[*ap - 1];
429 touch(mp);
430 setdot(mp);
432 if ((rp = hfield1("reply-to", mp)) != NULL &&
433 (cp = ok_vlook(reply_to_honour)) != NULL &&
434 (rt = checkaddrs(lextract(rp, GTO | gf), EACM_STRICT, NULL)
435 ) != NULL) {
436 char *sp;
437 size_t l;
438 char const *tr;
440 tr = _("Reply-To %s%s");
441 l = strlen(tr) + strlen(rt->n_name) + 3 +1;
442 sp = n_autorec_alloc(l);
443 snprintf(sp, l, tr, rt->n_name, (rt->n_flink != NULL ? "..."
444 : n_empty));
446 if(quadify(cp, UIZ_MAX, sp, TRU1) > FAL0){
447 head.h_to = cat(head.h_to, rt);
448 continue;
452 if ((cp = hfield1("from", mp)) == NULL)
453 cp = nameof(mp, 2);
454 head.h_to = cat(head.h_to, lextract(cp, GTO | gf));
456 if (head.h_to == NULL) /* XXX no recipients? */
457 goto jleave;
458 head.h_mailx_raw_to = namelist_dup(head.h_to, GTO | gf);
460 mp = &message[msgvec[0] - 1];
461 head.h_subject = hfield1("subject", mp);
462 head.h_subject = a_crese_reedit(head.h_subject);
463 make_ref_and_cs(mp, &head);
464 head.h_mailx_command = "reply";
465 head.h_mailx_orig_from = lextract(hfield1("from", mp), GIDENT | gf);
466 head.h_mailx_orig_to = lextract(hfield1("to", mp), GTO | gf);
467 head.h_mailx_orig_cc = lextract(hfield1("cc", mp), GCC | gf);
468 head.h_mailx_orig_bcc = lextract(hfield1("bcc", mp), GBCC | gf);
470 if (ok_blook(quote_as_attachment)) {
471 head.h_attach = csalloc(1, sizeof *head.h_attach);
472 head.h_attach->a_msgno = *msgvec;
473 head.h_attach->a_content_description = _("Original message content");
476 if (mail1(&head, 1, mp, NULL, recipient_record, 0) != OKAY) {
477 msgvec = NULL;
478 goto jleave;
481 if(ok_blook(markanswered) && !(mp->m_flag & MANSWERED))
482 mp->m_flag |= MANSWER | MANSWERED;
483 jleave:
484 NYD_LEAVE;
485 return (msgvec == NULL);
488 static int
489 _fwd(char *str, int recipient_record)
491 struct header head;
492 int *msgvec, rv = 1;
493 struct message *mp;
494 enum gfield gf;
495 bool_t f, forward_as_attachment;
496 char *recipient;
497 NYD_ENTER;
499 if ((recipient = laststring(str, &f, TRU1)) == NULL) {
500 fputs(_("No recipient specified.\n"), n_stdout);
501 goto jleave;
504 forward_as_attachment = ok_blook(forward_as_attachment);
505 gf = ok_blook(fullnames) ? GFULL | GSKIN : GSKIN;
506 msgvec = salloc((msgCount + 2) * sizeof *msgvec);
508 if (!f) {
509 *msgvec = first(0, MMNORM);
510 if (*msgvec == 0) {
511 if (n_pstate & (n_PS_HOOK_MASK | n_PS_ROBOT)) {
512 rv = 0;
513 goto jleave;
515 fprintf(n_stdout, _("No messages to forward.\n"));
516 goto jleave;
518 msgvec[1] = 0;
519 } else if (getmsglist(str, msgvec, 0) < 0)
520 goto jleave;
522 if (*msgvec == 0) {
523 if (n_pstate & (n_PS_HOOK_MASK | n_PS_ROBOT)) {
524 rv = 0;
525 goto jleave;
527 fprintf(n_stdout, _("No applicable messages.\n"));
528 goto jleave;
530 if (msgvec[1] != 0) {
531 fprintf(n_stdout, _("Cannot forward multiple messages at once\n"));
532 goto jleave;
535 memset(&head, 0, sizeof head);
536 if ((head.h_to = lextract(recipient,
537 (GTO | (ok_blook(fullnames) ? GFULL : GSKIN)))) == NULL)
538 goto jleave;
540 mp = &message[*msgvec - 1];
541 touch(mp);
542 setdot(mp);
543 head.h_subject = hfield1("subject", mp);
544 head.h_subject = __fwdedit(head.h_subject);
545 head.h_mailx_command = "forward";
546 head.h_mailx_raw_to = namelist_dup(head.h_to, GTO | gf);
547 head.h_mailx_orig_from = lextract(hfield1("from", mp), GIDENT | gf);
548 head.h_mailx_orig_to = lextract(hfield1("to", mp), GTO | gf);
549 head.h_mailx_orig_cc = lextract(hfield1("cc", mp), GCC | gf);
550 head.h_mailx_orig_bcc = lextract(hfield1("bcc", mp), GBCC | gf);
552 if (forward_as_attachment) {
553 head.h_attach = csalloc(1, sizeof *head.h_attach);
554 head.h_attach->a_msgno = *msgvec;
555 head.h_attach->a_content_description = _("Forwarded message");
557 rv = (mail1(&head, 1, (forward_as_attachment ? NULL : mp), NULL,
558 recipient_record, 1) != OKAY); /* reverse! */
559 jleave:
560 NYD_LEAVE;
561 return rv;
564 static char *
565 __fwdedit(char *subj)
567 struct str in, out;
568 char *newsubj = NULL;
569 NYD_ENTER;
571 if (subj == NULL || *subj == '\0')
572 goto jleave;
574 in.s = subj;
575 in.l = strlen(subj);
576 mime_fromhdr(&in, &out, TD_ISPR | TD_ICONV);
578 newsubj = salloc(out.l + 6);
579 memcpy(newsubj, "Fwd: ", 5); /* XXX localizable */
580 memcpy(newsubj + 5, out.s, out.l +1);
581 free(out.s);
582 jleave:
583 NYD_LEAVE;
584 return newsubj;
587 static int
588 _resend1(void *v, bool_t add_resent)
590 struct header head;
591 struct name *myto, *myrawto;
592 enum gfield gf;
593 char *name, *str;
594 int *ip, *msgvec;
595 bool_t f = TRU1;
596 NYD_ENTER;
598 str = v;
599 msgvec = salloc((msgCount + 2) * sizeof *msgvec);
600 name = laststring(str, &f, TRU1);
601 if (name == NULL) {
602 fputs(_("No recipient specified.\n"), n_stdout);
603 goto jleave;
606 if (!f) {
607 *msgvec = first(0, MMNORM);
608 if (*msgvec == 0) {
609 if (n_pstate & (n_PS_HOOK_MASK | n_PS_ROBOT)) {
610 f = FAL0;
611 goto jleave;
613 fputs(_("No applicable messages.\n"), n_stdout);
614 goto jleave;
616 msgvec[1] = 0;
617 } else if (getmsglist(str, msgvec, 0) < 0)
618 goto jleave;
620 if (*msgvec == 0) {
621 if (n_pstate & (n_PS_HOOK_MASK | n_PS_ROBOT)) {
622 f = FAL0;
623 goto jleave;
625 fprintf(n_stdout, "No applicable messages.\n");
626 goto jleave;
629 f = TRU1;
630 gf = ok_blook(fullnames) ? GFULL | GSKIN : GSKIN;
632 myrawto = nalloc(name, GTO | gf);
633 myto = usermap(namelist_dup(myrawto, myrawto->n_type), FAL0);
634 myto = n_alternates_remove(myto, TRU1);
635 if(myto == NULL){
636 n_err(_("No recipients specified\n"));
637 goto jleave;
640 n_autorec_relax_create();
641 for (ip = msgvec; *ip != 0 && UICMP(z, PTR2SIZE(ip - msgvec), <, msgCount);
642 ++ip){
643 struct message *mp;
645 mp = &message[*ip - 1];
646 touch(mp);
647 setdot(mp);
649 memset(&head, 0, sizeof head);
650 head.h_to = myto;
651 head.h_mailx_command = "resend";
652 head.h_mailx_raw_to = myrawto;
653 head.h_mailx_orig_from = lextract(hfield1("from", mp), GIDENT | gf);
654 head.h_mailx_orig_to = lextract(hfield1("to", mp), GTO | gf);
655 head.h_mailx_orig_cc = lextract(hfield1("cc", mp), GCC | gf);
656 head.h_mailx_orig_bcc = lextract(hfield1("bcc", mp), GBCC | gf);
658 if(resend_msg(mp, &head, add_resent) != OKAY){
659 /* n_autorec_relax_gut(); XXX but is handled automatically? */
660 goto jleave;
662 n_autorec_relax_unroll();
664 n_autorec_relax_gut();
665 f = FAL0;
666 jleave:
667 NYD_LEAVE;
668 return (f != FAL0);
671 FL int
672 c_reply(void *v)
674 int rv;
675 NYD_ENTER;
677 rv = (*_reply_or_Reply('r'))(v, FAL0);
678 NYD_LEAVE;
679 return rv;
682 FL int
683 c_replyall(void *v)
685 int rv;
686 NYD_ENTER;
688 rv = _reply(v, FAL0);
689 NYD_LEAVE;
690 return rv;
693 FL int
694 c_replysender(void *v)
696 int rv;
697 NYD_ENTER;
699 rv = _Reply(v, FAL0);
700 NYD_LEAVE;
701 return rv;
704 FL int
705 c_Reply(void *v)
707 int rv;
708 NYD_ENTER;
710 rv = (*_reply_or_Reply('R'))(v, FAL0);
711 NYD_LEAVE;
712 return rv;
715 FL int
716 c_Lreply(void *v)
718 int rv;
719 NYD_ENTER;
721 rv = a_crese_list_reply(v, HF_LIST_REPLY);
722 NYD_LEAVE;
723 return rv;
726 FL int
727 c_followup(void *v)
729 int rv;
730 NYD_ENTER;
732 rv = (*_reply_or_Reply('r'))(v, TRU1);
733 NYD_LEAVE;
734 return rv;
737 FL int
738 c_followupall(void *v)
740 int rv;
741 NYD_ENTER;
743 rv = _reply(v, TRU1);
744 NYD_LEAVE;
745 return rv;
748 FL int
749 c_followupsender(void *v)
751 int rv;
752 NYD_ENTER;
754 rv = _Reply(v, TRU1);
755 NYD_LEAVE;
756 return rv;
759 FL int
760 c_Followup(void *v)
762 int rv;
763 NYD_ENTER;
765 rv = (*_reply_or_Reply('R'))(v, TRU1);
766 NYD_LEAVE;
767 return rv;
770 FL int
771 c_forward(void *v)
773 int rv;
774 NYD_ENTER;
776 rv = _fwd(v, 0);
777 NYD_LEAVE;
778 return rv;
781 FL int
782 c_Forward(void *v)
784 int rv;
785 NYD_ENTER;
787 rv = _fwd(v, 1);
788 NYD_LEAVE;
789 return rv;
792 FL int
793 c_resend(void *v)
795 int rv;
796 NYD_ENTER;
798 rv = _resend1(v, TRU1);
799 NYD_LEAVE;
800 return rv;
803 FL int
804 c_Resend(void *v)
806 int rv;
807 NYD_ENTER;
809 rv = _resend1(v, FAL0);
810 NYD_LEAVE;
811 return rv;
814 /* s-it-mode */