1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ Still more user commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2014 Steffen "Daode" Nurpmeso <sdaoden@users.sf.net>.
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
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 the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its 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 THE REGENTS 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 THE REGENTS 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
40 #ifndef HAVE_AMALGAMATION
44 static char * _bang_buf
;
45 static size_t _bang_size
;
47 /* Modify subject we reply to to begin with Re: if it does not already */
48 static char * _reedit(char *subj
);
50 /* Expand the shell escape by expanding unescaped !'s into the last issued
51 * command where possible */
52 static void _bangexp(char **str
, size_t *size
);
54 static void make_ref_and_cs(struct message
*mp
, struct header
*head
);
56 /* Get PTF to implementation of command `c' (i.e., take care for *flipr*) */
57 static int (* respond_or_Respond(int c
))(int *, int);
59 /* Reply to a single message. Extract each name from the message header and
60 * send them off to mail1() */
61 static int respond_internal(int *msgvec
, int recipient_record
);
63 /* Reply to a series of messages by simply mailing to the senders and not
64 * messing around with the To: and Cc: lists as in normal reply */
65 static int Respond_internal(int *msgvec
, int recipient_record
);
67 /* Forward a message to a new recipient, in the sense of RFC 2822 */
68 static int forward1(char *str
, int recipient_record
);
70 /* Modify the subject we are replying to to begin with Fwd: */
71 static char * fwdedit(char *subj
);
73 /* Sort the passed string vecotor into ascending dictionary order */
74 static void asort(char **list
);
76 /* Do a dictionary order comparison of the arguments from qsort */
77 static int diction(const void *a
, const void *b
);
79 /* Do the real work of resending */
80 static int resend1(void *v
, int add_resent
);
83 static void list_shortcuts(void);
86 static enum okay
delete_shortcut(char const *str
);
95 if (subj
== NULL
|| *subj
== '\0')
100 mime_fromhdr(&in
, &out
, TD_ISPR
| TD_ICONV
);
102 /* XXX _reedit: we should take into account Aw: etc. (see mime.c!) */
103 if ((out
.s
[0] == 'r' || out
.s
[0] == 'R') &&
104 (out
.s
[1] == 'e' || out
.s
[1] == 'E') && out
.s
[2] == ':') {
105 newsubj
= savestr(out
.s
);
108 newsubj
= salloc(out
.l
+ 5);
109 sstpcpy(sstpcpy(newsubj
, "Re: "), out
.s
);
118 _bangexp(char **str
, size_t *size
)
123 size_t sz
, i
, j
, bangbufsize
;
126 dobang
= ok_blook(bang
);
128 bangbuf
= smalloc(bangbufsize
= *size
);
132 if ((*str
)[i
] == '!') {
133 sz
= strlen(_bang_buf
);
134 bangbuf
= srealloc(bangbuf
, bangbufsize
+= sz
);
136 memcpy(bangbuf
+ j
, _bang_buf
, sz
+ 1);
142 if ((*str
)[i
] == '\\' && (*str
)[i
+ 1] == '!') {
147 bangbuf
[j
++] = (*str
)[i
++];
151 printf("!%s\n", bangbuf
);
156 *str
= srealloc(*str
, *size
= sz
);
157 memcpy(*str
, bangbuf
, sz
);
159 _bang_buf
= srealloc(_bang_buf
, _bang_size
= sz
);
160 memcpy(_bang_buf
, bangbuf
, sz
);
166 make_ref_and_cs(struct message
*mp
, struct header
*head
)
168 char *oldref
, *oldmsgid
, *newref
, *cp
;
169 size_t oldreflen
= 0, oldmsgidlen
= 0, reflen
;
174 oldref
= hfield1("references", mp
);
175 oldmsgid
= hfield1("message-id", mp
);
176 if (oldmsgid
== NULL
|| *oldmsgid
== '\0') {
182 oldreflen
= strlen(oldref
);
183 reflen
+= oldreflen
+ 2;
186 oldmsgidlen
= strlen(oldmsgid
);
187 reflen
+= oldmsgidlen
;
190 newref
= ac_alloc(reflen
);
191 if (oldref
!= NULL
) {
192 memcpy(newref
, oldref
, oldreflen
+ 1);
193 if (oldmsgid
!= NULL
) {
194 newref
[oldreflen
++] = ',';
195 newref
[oldreflen
++] = ' ';
196 memcpy(newref
+ oldreflen
, oldmsgid
, oldmsgidlen
+ 1);
199 memcpy(newref
, oldmsgid
, oldmsgidlen
+ 1);
200 n
= extract(newref
, GREF
);
203 /* Limit the references to 21 entries */
204 while (n
->n_flink
!= NULL
)
206 for (i
= 1; i
< 21; ++i
) {
207 if (n
->n_blink
!= NULL
)
214 if (ok_blook(reply_in_same_charset
) &&
215 (cp
= hfield1("content-type", mp
)) != NULL
)
216 head
->h_charset
= mime_getparam("charset", cp
);
222 (*respond_or_Respond(int c
))(int *, int)
225 int (*rv
)(int*, int);
228 opt
+= ok_blook(Replyall
);
229 opt
+= ok_blook(flipr
);
230 rv
= ((opt
== 1) ^ (c
== 'R')) ? &Respond_internal
: &respond_internal
;
236 respond_internal(int *msgvec
, int recipient_record
)
241 struct name
*np
= NULL
;
246 gf
= ok_blook(fullnames
) ? GFULL
: GSKIN
;
248 if (msgvec
[1] != 0) {
249 fprintf(stderr
, tr(37,
250 "Sorry, can't reply to multiple messages at once\n"));
254 mp
= &message
[msgvec
[0] - 1];
258 if ((rcv
= hfield1("reply-to", mp
)) == NULL
)
259 if ((rcv
= hfield1("from", mp
)) == NULL
)
262 np
= lextract(rcv
, GTO
| gf
);
263 if (!ok_blook(recipients_in_cc
) && (cp
= hfield1("to", mp
)) != NULL
)
264 np
= cat(np
, lextract(cp
, GTO
| gf
));
265 /* Delete my name from reply list, and with it, all my alternate names */
266 np
= elide(delete_alternates(np
));
268 np
= lextract(rcv
, GTO
| gf
);
270 memset(&head
, 0, sizeof head
);
272 head
.h_subject
= hfield1("subject", mp
);
273 head
.h_subject
= _reedit(head
.h_subject
);
277 if (ok_blook(recipients_in_cc
) && (cp
= hfield1("to", mp
)) != NULL
)
278 np
= lextract(cp
, GCC
| gf
);
279 if ((cp
= hfield1("cc", mp
)) != NULL
)
280 np
= cat(np
, lextract(cp
, GCC
| gf
));
282 head
.h_cc
= elide(delete_alternates(np
));
283 make_ref_and_cs(mp
, &head
);
285 if (ok_blook(quote_as_attachment
)) {
286 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
287 head
.h_attach
->a_msgno
= *msgvec
;
288 head
.h_attach
->a_content_description
= tr(512,
289 "Original message content");
292 if (mail1(&head
, 1, mp
, NULL
, recipient_record
, 0) == OKAY
&&
293 ok_blook(markanswered
) && (mp
->m_flag
& MANSWERED
) == 0)
294 mp
->m_flag
|= MANSWER
| MANSWERED
;
302 Respond_internal(int *msgvec
, int recipient_record
)
311 memset(&head
, 0, sizeof head
);
312 gf
= ok_blook(fullnames
) ? GFULL
: GSKIN
;
314 for (ap
= msgvec
; *ap
!= 0; ++ap
) {
315 mp
= &message
[*ap
- 1];
318 if ((cp
= hfield1("reply-to", mp
)) == NULL
)
319 if ((cp
= hfield1("from", mp
)) == NULL
)
321 head
.h_to
= cat(head
.h_to
, lextract(cp
, GTO
| gf
));
323 if (head
.h_to
== NULL
)
326 mp
= &message
[msgvec
[0] - 1];
327 head
.h_subject
= hfield1("subject", mp
);
328 head
.h_subject
= _reedit(head
.h_subject
);
329 make_ref_and_cs(mp
, &head
);
331 if (ok_blook(quote_as_attachment
)) {
332 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
333 head
.h_attach
->a_msgno
= *msgvec
;
334 head
.h_attach
->a_content_description
= tr(512,
335 "Original message content");
338 if (mail1(&head
, 1, mp
, NULL
, recipient_record
, 0) == OKAY
&&
339 ok_blook(markanswered
) && (mp
->m_flag
& MANSWERED
) == 0)
340 mp
->m_flag
|= MANSWER
| MANSWERED
;
347 forward1(char *str
, int recipient_record
)
353 bool_t f
, forward_as_attachment
;
356 if ((recipient
= laststring(str
, &f
, 0)) == NULL
) {
357 puts(tr(47, "No recipient specified."));
361 forward_as_attachment
= ok_blook(forward_as_attachment
);
362 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
365 *msgvec
= first(0, MMNORM
);
371 printf("No messages to forward.\n");
375 } else if (getmsglist(str
, msgvec
, 0) < 0)
383 printf("No applicable messages.\n");
386 if (msgvec
[1] != 0) {
387 printf("Cannot forward multiple messages at once\n");
391 memset(&head
, 0, sizeof head
);
392 if ((head
.h_to
= lextract(recipient
, GTO
|
393 (ok_blook(fullnames
) ? GFULL
: GSKIN
))) == NULL
)
396 mp
= &message
[*msgvec
- 1];
398 if (forward_as_attachment
) {
399 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
400 head
.h_attach
->a_msgno
= *msgvec
;
401 head
.h_attach
->a_content_description
= "Forwarded message";
406 head
.h_subject
= hfield1("subject", mp
);
407 head
.h_subject
= fwdedit(head
.h_subject
);
408 mail1(&head
, 1, (forward_as_attachment
? NULL
: mp
), NULL
, recipient_record
,
420 char *newsubj
= NULL
;
423 if (subj
== NULL
|| *subj
== '\0')
428 mime_fromhdr(&in
, &out
, TD_ISPR
| TD_ICONV
);
430 newsubj
= salloc(out
.l
+ 6);
431 memcpy(newsubj
, "Fwd: ", 5);
432 memcpy(newsubj
+ 5, out
.s
, out
.l
+ 1);
445 for (ap
= list
; *ap
!= NULL
; ++ap
)
447 if (PTR2SIZE(ap
- list
) >= 2)
448 qsort(list
, PTR2SIZE(ap
- list
), sizeof *list
, diction
);
453 diction(const void *a
, const void *b
)
458 rv
= strcmp(*(char**)UNCONST(a
), *(char**)UNCONST(b
));
464 resend1(void *v
, int add_resent
)
467 struct name
*to
, *sn
;
473 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
474 name
= laststring(str
, &f
, 1);
476 puts(tr(47, "No recipient specified."));
481 *msgvec
= first(0, MMNORM
);
487 puts(tr(48, "No applicable messages."));
491 } else if (getmsglist(str
, msgvec
, 0) < 0)
499 printf("No applicable messages.\n");
503 sn
= nalloc(name
, GTO
);
504 to
= usermap(sn
, FAL0
);
505 for (ip
= msgvec
; *ip
!= 0 && UICMP(z
, PTR2SIZE(ip
- msgvec
), <, msgCount
);
507 if (resend_msg(&message
[*ip
- 1], to
, add_resent
) != OKAY
)
521 for (s
= shortcuts
; s
; s
= s
->sh_next
)
522 printf("%s=%s\n", s
->sh_short
, s
->sh_long
);
527 delete_shortcut(char const *str
)
529 struct shortcut
*sp
, *sq
;
533 for (sp
= shortcuts
, sq
= NULL
; sp
; sq
= sp
, sp
= sp
->sh_next
) {
534 if (strcmp(sp
->sh_short
, str
) == 0) {
538 sq
->sh_next
= sp
->sh_next
;
540 shortcuts
= sp
->sh_next
;
553 char const *sh
= NULL
;
556 sighandler_type sigint
;
559 cmd
= smalloc(cmdsize
= strlen(str
) + 1);
560 memcpy(cmd
, str
, cmdsize
);
561 _bangexp(&cmd
, &cmdsize
);
562 if ((sh
= ok_vlook(SHELL
)) == NULL
)
565 sigint
= safe_signal(SIGINT
, SIG_IGN
);
566 run_command(sh
, 0, -1, -1, "-c", cmd
, NULL
);
567 safe_signal(SIGINT
, sigint
);
578 sighandler_type sigint
;
583 if ((sh
= ok_vlook(SHELL
)) == NULL
)
586 sigint
= safe_signal(SIGINT
, SIG_IGN
);
587 run_command(sh
, 0, -1, -1, NULL
, NULL
, NULL
);
588 safe_signal(SIGINT
, sigint
);
604 #ifdef HAVE_DOCSTRINGS
605 ret
= !print_comm_docstr(arg
);
607 fprintf(stderr
, tr(91, "Unknown command: `%s'\n"), arg
);
609 ret
= ccmdnotsupp(NULL
);
614 /* Very ugly, but take care for compiler supported string lengths :( */
615 printf(tr(295, "%s commands:\n"), progname
);
617 "type <message list> type messages\n"
618 "next goto and type next message\n"
619 "from <message list> give head lines of messages\n"
620 "headers print out active message headers\n"
621 "delete <message list> delete messages\n"
622 "undelete <message list> undelete messages\n"));
624 "save <message list> folder append messages to folder and mark as saved\n"
625 "copy <message list> folder append messages to folder without marking them\n"
626 "write <message list> file append message texts to file, save attachments\n"
627 "preserve <message list> keep incoming messages in mailbox even if saved\n"
628 "Reply <message list> reply to message senders\n"
629 "reply <message list> reply to message senders and all recipients\n"));
631 "mail addresses mail to specific recipients\n"
632 "file folder change to another folder\n"
633 "quit quit and apply changes to folder\n"
634 "xit quit and discard changes made to folder\n"
636 "cd <directory> chdir to directory or home if none given\n"
637 "list list names of all available commands\n"));
639 "\nA <message list> consists of integers, ranges of same, or other criteria\n"
640 "separated by spaces. If omitted, %s uses the last message typed.\n"),
651 char buf
[PATH_MAX
]; /* TODO getcwd(3) may return a larger value */
654 if (getcwd(buf
, sizeof buf
) != NULL
) {
672 if (*arglist
== NULL
)
674 else if ((cp
= file_expand(*arglist
)) == NULL
)
691 rv
= (*respond_or_Respond('r'))(v
, 0);
702 rv
= respond_internal(v
, 0);
708 respondsender(void *v
)
713 rv
= Respond_internal(v
, 0);
724 rv
= (*respond_or_Respond('R'))(v
, 0);
735 rv
= (*respond_or_Respond('r'))(v
, 1);
746 rv
= respond_internal(v
, 1);
752 followupsender(void *v
)
757 rv
= Respond_internal(v
, 1);
768 rv
= (*respond_or_Respond('R'))(v
, 1);
820 int *msgvec
= v
, *ip
, mesg
, rv
= 1;
825 printf(tr(39, "Cannot \"preserve\" in edit mode\n"));
829 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
831 mp
= &message
[mesg
- 1];
832 mp
->m_flag
|= MPRESERVE
;
835 did_print_dot
= TRU1
;
846 int *msgvec
= v
, *ip
;
849 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
850 setdot(&message
[*ip
- 1]);
851 dot
->m_flag
&= ~(MREAD
| MTOUCH
);
852 dot
->m_flag
|= MSTATUS
;
854 if (mb
.mb_type
== MB_IMAP
|| mb
.mb_type
== MB_CACHE
)
855 imap_unread(&message
[*ip
- 1], *ip
); /* TODO return? */
857 did_print_dot
= TRU1
;
866 int *msgvec
= v
, *ip
;
869 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
870 setdot(&message
[*ip
- 1]);
871 touch(&message
[*ip
- 1]);
880 int *msgvec
= v
, *ip
, mesg
;
884 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
886 mp
= &message
[mesg
- 1];
887 printf("%d: ", mesg
);
888 if (mp
->m_xlines
> 0)
889 printf("%ld", mp
->m_xlines
);
892 printf("/%lu\n", (ul_it
)mp
->m_xsize
);
914 char **ap
= v
, *cp
, *cp2
, *varbuf
, c
;
923 for (; *ap
!= NULL
; ++ap
) {
925 cp2
= varbuf
= ac_alloc(strlen(cp
) + 1);
926 for (; (c
= *cp
) != '=' && c
!= '\0'; ++cp
)
934 fprintf(stderr
, tr(41, "Non-null variable name required\n"));
938 if (varbuf
[0] == 'n' && varbuf
[1] == 'o')
939 errs
+= _var_vokclear(&varbuf
[2]);
941 errs
+= _var_vokset(varbuf
, (uintptr_t)cp
);
958 for (ap
= v
; *ap
!= NULL
; ++ap
)
959 errs
+= _var_vokclear(*ap
);
967 char **argv
= v
, **ap
, *gname
, **p
;
968 struct grouphead
*gh
;
974 for (h
= 0, s
= 1; h
< HSHSIZE
; ++h
)
975 for (gh
= groups
[h
]; gh
!= NULL
; gh
= gh
->g_link
)
977 ap
= salloc(s
* sizeof *ap
);
978 for (h
= 0, p
= ap
; h
< HSHSIZE
; ++h
)
979 for (gh
= groups
[h
]; gh
!= NULL
; gh
= gh
->g_link
)
983 for (p
= ap
; *p
!= NULL
; ++p
)
988 if (argv
[1] == NULL
) {
995 if ((gh
= findgroup(gname
)) == NULL
) {
996 gh
= scalloc(1, sizeof *gh
);
997 gh
->g_name
= sstrdup(gname
);
999 gh
->g_link
= groups
[h
];
1003 /* Insert names from the command list into the group. Who cares if there
1004 * are duplicates? They get tossed later anyway */
1005 for (ap
= argv
+ 1; *ap
!= NULL
; ++ap
) {
1006 gp
= scalloc(1, sizeof *gp
);
1007 gp
->ge_name
= sstrdup(*ap
);
1008 gp
->ge_link
= gh
->g_list
;
1023 if (*argv
== NULL
) {
1024 fprintf(stderr
, tr(209, "Must specify alias to remove\n"));
1029 remove_group(*argv
);
1030 while (*++argv
!= NULL
);
1044 if (*argv
== NULL
) {
1051 fprintf(stderr
, tr(516, "Cannot change folder from within a hook.\n"));
1056 save_mbox_for_possible_quitstuff();
1058 i
= setfile(*argv
, 0);
1063 callhook(mailname
, 0);
1064 if (i
> 0 && !ok_blook(emptystart
)) {
1068 announce(ok_blook(bsdcompat
) || ok_blook(bsdannounce
));
1078 char const **argv
= v
, **ap
, *cp
;
1082 for (ap
= argv
; *ap
!= NULL
; ++ap
) {
1084 if ((cp
= fexpand(cp
, FEXP_NSHORTCUT
)) != NULL
) {
1088 while (*cp
!= '\0' && (c
= expand_shell_escape(&cp
, FAL0
)) > 0)
1090 /* \c ends overall processing */
1105 char **argv
= v
, *cp
, *op
;
1108 if (cond_state
!= COND_ANY
) {
1109 fprintf(stderr
, tr(42, "Illegal nested \"if\"\n"));
1114 if (*cp
!= '$' && argv
[1] != NULL
) {
1116 fprintf(stderr
, tr(528, "Invalid conditional expression \"%s %s %s\"\n"),
1117 argv
[0], (argv
[1] != NULL
? argv
[1] : ""),
1118 (argv
[2] != NULL
? argv
[2] : ""));
1119 cond_state
= COND_ANY
;
1125 cond_state
= COND_NOEXEC
;
1128 cond_state
= COND_EXEC
;
1131 cond_state
= COND_RCV
;
1134 cond_state
= COND_SEND
;
1137 cond_state
= COND_TERM
;
1140 /* Look up the value in question, we need it anyway */
1141 v
= vok_vlook(++cp
);
1143 /* Single argument, "implicit boolean" form? */
1144 if ((op
= argv
[1]) == NULL
) {
1145 cond_state
= (v
== NULL
) ? COND_NOEXEC
: COND_EXEC
;
1149 /* Three argument comparison form? */
1150 if (argv
[2] == NULL
|| op
[0] == '\0' || op
[1] != '=' || op
[2] != '\0')
1152 /* A null value is treated as the empty string */
1155 if (strcmp(v
, argv
[2]))
1160 cond_state
= (((op
[0] == '!') ^ (v
== NULL
))
1161 ? COND_NOEXEC
: COND_EXEC
);
1168 fprintf(stderr
, tr(43, "Unrecognized if-keyword: \"%s\"\n"), cp
);
1169 cond_state
= COND_ANY
;
1185 switch (cond_state
) {
1187 fprintf(stderr
, tr(44, "\"Else\" without matching \"if\"\n"));
1190 cond_state
= COND_RCV
;
1193 cond_state
= COND_SEND
;
1196 cond_state
= COND_NOTERM
;
1199 cond_state
= COND_NOEXEC
;
1202 cond_state
= COND_EXEC
;
1205 fprintf(stderr
, tr(45, "Mail's idea of conditions is screwed up\n"));
1206 cond_state
= COND_ANY
;
1222 if (cond_state
== COND_ANY
) {
1223 fprintf(stderr
, tr(46, "\"Endif\" without matching \"if\"\n"));
1226 cond_state
= COND_ANY
;
1237 char **namelist
= v
, **ap
, **ap2
, *cp
;
1240 l
= argcount(namelist
) + 1;
1242 if (altnames
== NULL
)
1244 for (ap
= altnames
; *ap
!= NULL
; ++ap
)
1250 if (altnames
!= NULL
) {
1251 for (ap
= altnames
; *ap
!= NULL
; ++ap
)
1255 altnames
= smalloc(l
* sizeof(char*));
1256 for (ap
= namelist
, ap2
= altnames
; *ap
!= NULL
; ++ap
, ++ap2
) {
1257 l
= strlen(*ap
) + 1;
1277 (mb
.mb_type
!= MB_IMAP
|| imap_newmail(1)) &&
1279 (val
= setfile(mailname
, 1)) == 0) {
1281 setdot(&message
[mdot
- 1]);
1295 if (args
[0] == NULL
) {
1302 if (args
[1] == NULL
) {
1303 fprintf(stderr
, tr(220, "expansion name for shortcut missing\n"));
1306 if (args
[2] != NULL
) {
1307 fprintf(stderr
, tr(221, "too many arguments\n"));
1311 if ((s
= get_shortcut(args
[0])) != NULL
) {
1313 s
->sh_long
= sstrdup(args
[1]);
1315 s
= scalloc(1, sizeof *s
);
1316 s
->sh_short
= sstrdup(args
[0]);
1317 s
->sh_long
= sstrdup(args
[1]);
1318 s
->sh_next
= shortcuts
;
1327 FL
struct shortcut
*
1328 get_shortcut(char const *str
)
1333 for (s
= shortcuts
; s
!= NULL
; s
= s
->sh_next
)
1334 if (!strcmp(str
, s
->sh_short
))
1347 if (args
[0] == NULL
) {
1348 fprintf(stderr
, tr(222, "need shortcut names to remove\n"));
1353 while (*args
!= NULL
) {
1354 if (delete_shortcut(*args
) != OKAY
) {
1356 fprintf(stderr
, tr(223, "%s: no such shortcut\n"), *args
);
1369 int *msgvec
= v
, *ip
;
1372 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
1373 m
= &message
[*ip
- 1];
1375 if ((m
->m_flag
& (MFLAG
| MFLAGGED
)) == 0)
1376 m
->m_flag
|= MFLAG
| MFLAGGED
;
1386 int *msgvec
= v
, *ip
;
1389 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
1390 m
= &message
[*ip
- 1];
1392 if (m
->m_flag
& (MFLAG
| MFLAGGED
)) {
1393 m
->m_flag
&= ~(MFLAG
| MFLAGGED
);
1394 m
->m_flag
|= MUNFLAG
;
1405 int *msgvec
= v
, *ip
;
1408 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
1409 m
= &message
[*ip
- 1];
1411 if ((m
->m_flag
& (MANSWER
| MANSWERED
)) == 0)
1412 m
->m_flag
|= MANSWER
| MANSWERED
;
1419 cunanswered(void *v
)
1422 int *msgvec
= v
, *ip
;
1425 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
1426 m
= &message
[*ip
- 1];
1428 if (m
->m_flag
& (MANSWER
| MANSWERED
)) {
1429 m
->m_flag
&= ~(MANSWER
| MANSWERED
);
1430 m
->m_flag
|= MUNANSWER
;
1441 int *msgvec
= v
, *ip
;
1444 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
1445 m
= &message
[*ip
- 1];
1447 if ((m
->m_flag
& (MDRAFT
| MDRAFTED
)) == 0)
1448 m
->m_flag
|= MDRAFT
| MDRAFTED
;
1458 int *msgvec
= v
, *ip
;
1461 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
1462 m
= &message
[*ip
- 1];
1464 if (m
->m_flag
& (MDRAFT
| MDRAFTED
)) {
1465 m
->m_flag
&= ~(MDRAFT
| MDRAFTED
);
1466 m
->m_flag
|= MUNDRAFT
;
1480 switch (mb
.mb_type
) {
1485 rv
= ccmdnotsupp(NULL
);
1492 rv
= ccmdnotsupp(NULL
);
1507 char **args
= v
, *name
;
1511 if (*args
== NULL
) {
1512 fprintf(stderr
, tr(290, "Syntax is: remove mailbox ...\n"));
1517 fmt
= tr(287, "Remove \"%s\" (y/n) ? ");
1518 fmt_len
= strlen(fmt
);
1520 if ((name
= expand(*args
)) == NULL
)
1523 if (!strcmp(name
, mailname
)) {
1524 fprintf(stderr
, tr(286, "Cannot remove current mailbox \"%s\".\n"),
1530 size_t vl
= strlen(name
) + fmt_len
+1;
1531 char *vb
= ac_alloc(vl
);
1533 snprintf(vb
, vl
, fmt
, name
);
1534 asw
= getapproval(vb
, TRU1
);
1540 switch (which_protocol(name
)) {
1542 if (unlink(name
) < 0) { /* TODO do not handle .gz .bz2 */
1548 fprintf(stderr
, tr(288, "Cannot remove POP3 mailbox \"%s\".\n"),name
);
1553 if (imap_remove(name
) != OKAY
)
1558 if (maildir_remove(name
) != OKAY
)
1562 fprintf(stderr
, tr(289, "Unknown protocol in \"%s\". Not removed.\n"),
1567 } while (*++args
!= NULL
);
1576 char **args
= v
, *old
, *new;
1577 enum protocol oldp
, newp
;
1583 if (args
[0] == NULL
|| args
[1] == NULL
|| args
[2] != NULL
) {
1584 fprintf(stderr
, "Syntax: rename old new\n");
1588 if ((old
= expand(args
[0])) == NULL
)
1590 oldp
= which_protocol(old
);
1591 if ((new = expand(args
[1])) == NULL
)
1593 newp
= which_protocol(new);
1595 if (!strcmp(old
, mailname
) || !strcmp(new, mailname
)) {
1596 fprintf(stderr
, tr(291, "Cannot rename current mailbox \"%s\".\n"), old
);
1599 if ((oldp
== PROTO_IMAP
|| newp
== PROTO_IMAP
) && oldp
!= newp
) {
1600 fprintf(stderr
, tr(292, "Can only rename folders of same type.\n"));
1606 if (newp
== PROTO_POP3
)
1610 if (link(old
, new) == -1) {
1624 } else if (unlink(old
) == -1) {
1630 if (rename(old
, new) == -1) {
1637 fprintf(stderr
, tr(293, "Cannot rename POP3 mailboxes.\n"));
1642 if (imap_rename(old
, new) != OKAY
)
1648 fprintf(stderr
, tr(294,
1649 "Unknown protocol in \"%s\" and \"%s\". Not renamed.\n"), old
, new);
1658 /* vim:set fenc=utf-8:s-it-mode */