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 - 2013 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 /* Modify subject we reply to to begin with Re: if it does not already */
45 static char * _reedit(char *subj
);
47 static int bangexp(char **str
, size_t *size
);
48 static void make_ref_and_cs(struct message
*mp
, struct header
*head
);
49 static int (* respond_or_Respond(int c
))(int *, int);
50 static int respond_internal(int *msgvec
, int recipient_record
);
51 static char * fwdedit(char *subj
);
52 static void asort(char **list
);
53 static int diction(const void *a
, const void *b
);
54 static int Respond_internal(int *msgvec
, int recipient_record
);
55 static int resend1(void *v
, int add_resent
);
56 static void list_shortcuts(void);
57 static enum okay
delete_shortcut(const char *str
);
65 if (subj
== NULL
|| *subj
== '\0')
70 mime_fromhdr(&in
, &out
, TD_ISPR
|TD_ICONV
);
72 if ((out
.s
[0] == 'r' || out
.s
[0] == 'R') &&
73 (out
.s
[1] == 'e' || out
.s
[1] == 'E') &&
75 newsubj
= savestr(out
.s
);
78 newsubj
= salloc(out
.l
+ 5);
79 sstpcpy(sstpcpy(newsubj
, "Re: "), out
.s
);
87 * Process a shell escape by saving signals, ignoring signals,
96 sighandler_type sigint
= safe_signal(SIGINT
, SIG_IGN
);
98 cmd
= smalloc(cmdsize
= strlen(str
) + 1);
99 memcpy(cmd
, str
, cmdsize
);
100 if (bangexp(&cmd
, &cmdsize
) < 0)
102 if ((sh
= value("SHELL")) == NULL
)
104 run_command(sh
, 0, -1, -1, "-c", cmd
, NULL
);
105 safe_signal(SIGINT
, sigint
);
112 * Fork an interactive shell.
118 sighandler_type sigint
= safe_signal(SIGINT
, SIG_IGN
);
122 if ((sh
= value("SHELL")) == NULL
)
124 run_command(sh
, 0, -1, -1, NULL
, NULL
, NULL
);
125 safe_signal(SIGINT
, sigint
);
131 * Expand the shell escape by expanding unescaped !'s into the
132 * last issued command where possible.
135 static char *lastbang
;
136 static size_t lastbangsize
;
139 bangexp(char **str
, size_t *size
)
143 int dobang
= value("bang") != NULL
;
144 size_t sz
, i
, j
, bangbufsize
;
146 bangbuf
= smalloc(bangbufsize
= *size
);
150 if ((*str
)[i
] == '!') {
151 sz
= strlen(lastbang
);
152 bangbuf
= srealloc(bangbuf
, bangbufsize
+= sz
);
154 memcpy(bangbuf
+ j
, lastbang
, sz
+ 1);
160 if ((*str
)[i
] == '\\' && (*str
)[i
+ 1] == '!') {
165 bangbuf
[j
++] = (*str
)[i
++];
169 printf("!%s\n", bangbuf
);
174 *str
= srealloc(*str
, *size
= sz
);
175 memcpy(*str
, bangbuf
, sz
);
176 if (sz
> lastbangsize
)
177 lastbang
= srealloc(lastbang
, lastbangsize
= sz
);
178 memcpy(lastbang
, bangbuf
, sz
);
188 char *arg
= *(char**)v
;
191 #ifdef HAVE_DOCSTRINGS
192 ret
= ! print_comm_docstr(arg
);
194 fprintf(stderr
, tr(91, "Unknown command: `%s'\n"), arg
);
196 ret
= ccmdnotsupp(NULL
);
201 /* Very ugly, but take care for compiler supported string lengths :( */
202 printf(tr(295, "%s commands:\n"), progname
);
204 "type <message list> type messages\n"
205 "next goto and type next message\n"
206 "from <message list> give head lines of messages\n"
207 "headers print out active message headers\n"
208 "delete <message list> delete messages\n"
209 "undelete <message list> undelete messages\n"));
211 "save <message list> folder append messages to folder and mark as saved\n"
212 "copy <message list> folder append messages to folder without marking them\n"
213 "write <message list> file append message texts to file, save attachments\n"
214 "preserve <message list> keep incoming messages in mailbox even if saved\n"
215 "Reply <message list> reply to message senders\n"
216 "reply <message list> reply to message senders and all recipients\n"));
218 "mail addresses mail to specific recipients\n"
219 "file folder change to another folder\n"
220 "quit quit and apply changes to folder\n"
221 "xit quit and discard changes made to folder\n"
223 "cd <directory> chdir to directory or home if none given\n"
224 "list list names of all available commands\n"));
226 "\nA <message list> consists of integers, ranges of same, or other criteria\n"
227 "separated by spaces. If omitted, %s uses the last message typed.\n"),
237 char buf
[MAXPATHLEN
]; /* TODO getcwd(3) may return a larger value */
239 if (getcwd(buf
, sizeof buf
) != NULL
) {
255 if (*arglist
== NULL
)
257 else if ((cp
= file_expand(*arglist
)) == NULL
)
268 make_ref_and_cs(struct message
*mp
, struct header
*head
)
270 char *oldref
, *oldmsgid
, *newref
, *cp
;
271 size_t oldreflen
= 0, oldmsgidlen
= 0, reflen
;
275 oldref
= hfield1("references", mp
);
276 oldmsgid
= hfield1("message-id", mp
);
277 if (oldmsgid
== NULL
|| *oldmsgid
== '\0') {
283 oldreflen
= strlen(oldref
);
284 reflen
+= oldreflen
+ 2;
287 oldmsgidlen
= strlen(oldmsgid
);
288 reflen
+= oldmsgidlen
;
291 newref
= ac_alloc(reflen
);
292 if (oldref
!= NULL
) {
293 memcpy(newref
, oldref
, oldreflen
+ 1);
294 if (oldmsgid
!= NULL
) {
295 newref
[oldreflen
++] = ',';
296 newref
[oldreflen
++] = ' ';
297 memcpy(newref
+ oldreflen
, oldmsgid
, oldmsgidlen
+ 1);
300 memcpy(newref
, oldmsgid
, oldmsgidlen
+ 1);
301 n
= extract(newref
, GREF
);
305 * Limit the references to 21 entries.
307 while (n
->n_flink
!= NULL
)
309 for (i
= 1; i
< 21; i
++) {
310 if (n
->n_blink
!= NULL
)
317 if (value("reply-in-same-charset") != NULL
&&
318 (cp
= hfield1("content-type", mp
)) != NULL
)
319 head
->h_charset
= mime_getparam("charset", cp
);
323 (*respond_or_Respond(int c
))(int *, int)
327 opt
+= (value("Replyall") != NULL
);
328 opt
+= (value("flipr") != NULL
);
329 return ((opt
== 1) ^ (c
== 'R')) ? Respond_internal
: respond_internal
;
335 return (respond_or_Respond('r'))((int *)v
, 0);
341 return respond_internal((int *)v
, 0);
345 respondsender(void *v
)
347 return Respond_internal((int *)v
, 0);
353 return (respond_or_Respond('r'))((int *)v
, 1);
359 return respond_internal((int *)v
, 1);
363 followupsender(void *v
)
365 return Respond_internal((int *)v
, 1);
369 * Reply to a single message. Extract each name from the
370 * message header and send them off to mail1()
373 respond_internal(int *msgvec
, int recipient_record
)
378 struct name
*np
= NULL
;
379 enum gfield gf
= boption("fullnames") ? GFULL
: GSKIN
;
381 if (msgvec
[1] != 0) {
382 fprintf(stderr
, tr(37,
383 "Sorry, can't reply to multiple messages at once\n"));
386 mp
= &message
[msgvec
[0] - 1];
390 if ((rcv
= hfield1("reply-to", mp
)) == NULL
)
391 if ((rcv
= hfield1("from", mp
)) == NULL
)
394 np
= lextract(rcv
, GTO
|gf
);
395 if (! boption("recipients-in-cc") && (cp
= hfield1("to", mp
)) != NULL
)
396 np
= cat(np
, lextract(cp
, GTO
| gf
));
398 * Delete my name from the reply list,
399 * and with it, all my alternate names.
401 np
= elide(delete_alternates(np
));
403 np
= lextract(rcv
, GTO
| gf
);
405 memset(&head
, 0, sizeof head
);
407 head
.h_subject
= hfield1("subject", mp
);
408 head
.h_subject
= _reedit(head
.h_subject
);
411 if (boption("recipients-in-cc") && (cp
= hfield1("to", mp
)) != NULL
)
412 np
= lextract(cp
, GCC
| gf
);
413 if ((cp
= hfield1("cc", mp
)) != NULL
)
414 np
= cat(np
, lextract(cp
, GCC
| gf
));
416 head
.h_cc
= elide(delete_alternates(np
));
417 make_ref_and_cs(mp
, &head
);
419 if (boption("quote-as-attachment")) {
420 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
421 head
.h_attach
->a_msgno
= *msgvec
;
422 head
.h_attach
->a_content_description
= tr(512,
423 "Original message content");
426 if (mail1(&head
, 1, mp
, NULL
, recipient_record
, 0) == OKAY
&&
427 boption("markanswered") &&
428 (mp
->m_flag
& MANSWERED
) == 0)
429 mp
->m_flag
|= MANSWER
| MANSWERED
;
434 * Forward a message to a new recipient, in the sense of RFC 2822.
437 forward1(char *str
, int recipient_record
)
443 bool_t f
, forward_as_attachment
;
445 forward_as_attachment
= boption("forward-as-attachment");
446 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
447 if ((recipient
= laststring(str
, &f
, 0)) == NULL
) {
448 puts(tr(47, "No recipient specified."));
452 *msgvec
= first(0, MMNORM
);
456 printf("No messages to forward.\n");
460 } else if (getmsglist(str
, msgvec
, 0) < 0)
465 printf("No applicable messages.\n");
468 if (msgvec
[1] != 0) {
469 printf("Cannot forward multiple messages at once\n");
472 memset(&head
, 0, sizeof head
);
473 if ((head
.h_to
= lextract(recipient
,
474 GTO
| (value("fullnames") ? GFULL
: GSKIN
))) == NULL
)
476 mp
= &message
[*msgvec
- 1];
477 if (forward_as_attachment
) {
478 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
479 head
.h_attach
->a_msgno
= *msgvec
;
480 head
.h_attach
->a_content_description
= "Forwarded message";
485 head
.h_subject
= hfield1("subject", mp
);
486 head
.h_subject
= fwdedit(head
.h_subject
);
487 mail1(&head
, 1, (forward_as_attachment
? NULL
: mp
),
488 NULL
, recipient_record
, 1);
493 * Modify the subject we are replying to to begin with Fwd:.
501 if (subj
== NULL
|| *subj
== '\0')
505 mime_fromhdr(&in
, &out
, TD_ISPR
|TD_ICONV
);
507 newsubj
= salloc(out
.l
+ 6);
508 memcpy(newsubj
, "Fwd: ", 5);
509 memcpy(newsubj
+ 5, out
.s
, out
.l
+ 1);
515 * The 'forward' command.
520 return forward1(v
, 0);
524 * Similar to forward, saving the message in a file named after the
530 return forward1(v
, 1);
534 * Preserve the named messages, so that they will be sent
535 * back to the system mailbox.
545 printf(tr(39, "Cannot \"preserve\" in edit mode\n"));
548 for (ip
= msgvec
; *ip
!= 0; ip
++) {
550 mp
= &message
[mesg
-1];
551 mp
->m_flag
|= MPRESERVE
;
555 * This is now Austin Group Request XCU #20.
557 did_print_dot
= TRU1
;
563 * Mark all given messages as unread.
571 for (ip
= msgvec
; *ip
!= 0; ip
++) {
572 setdot(&message
[*ip
-1]);
573 dot
->m_flag
&= ~(MREAD
|MTOUCH
);
574 dot
->m_flag
|= MSTATUS
;
576 if (mb
.mb_type
== MB_IMAP
|| mb
.mb_type
== MB_CACHE
)
577 imap_unread(&message
[*ip
-1], *ip
); /* TODO return? */
580 * The "unread" command is not part of POSIX mailx.
582 did_print_dot
= TRU1
;
588 * Mark all given messages as read.
596 for (ip
= msgvec
; *ip
; ip
++) {
597 setdot(&message
[*ip
-1]);
598 touch(&message
[*ip
-1]);
604 * Print the size of each message.
613 for (ip
= msgvec
; *ip
!= 0; ip
++) {
615 mp
= &message
[mesg
-1];
616 printf("%d: ", mesg
);
617 if (mp
->m_xlines
> 0)
618 printf("%ld", mp
->m_xlines
);
621 printf("/%lu\n", (unsigned long)mp
->m_xsize
);
627 * Quit quickly. If we are sourcing, just pop the input level
628 * by returning an error.
644 char **ap
= v
, *cp
, *cp2
, *varbuf
, c
;
652 for (; *ap
!= NULL
; ++ap
) {
654 cp2
= varbuf
= ac_alloc(strlen(cp
) + 1);
655 for (; (c
= *cp
) != '=' && c
!= '\0'; ++cp
)
664 tr(41, "Non-null variable name required\n"));
668 if (varbuf
[0] == 'n' && varbuf
[1] == 'o')
669 errs
+= unset_internal(&varbuf
[2]);
671 errs
+= assign(varbuf
, cp
);
672 jnext
: ac_free(varbuf
);
679 * Unset a bunch of variable values.
688 for (ap
= (char **)v
; *ap
!= NULL
; ap
++)
689 errs
+= unset_internal(*ap
);
694 * Put add users to a group.
700 struct grouphead
*gh
;
704 char **ap
, *gname
, **p
;
707 for (h
= 0, s
= 1; h
< HSHSIZE
; h
++)
708 for (gh
= groups
[h
]; gh
!= NULL
; gh
= gh
->g_link
)
711 ap
= (char **)salloc(s
* sizeof *ap
);
712 for (h
= 0, p
= ap
; h
< HSHSIZE
; h
++)
713 for (gh
= groups
[h
]; gh
!= NULL
; gh
= gh
->g_link
)
717 for (p
= ap
; *p
!= NULL
; p
++)
721 if (argv
[1] == NULL
) {
727 if ((gh
= findgroup(gname
)) == NULL
) {
728 gh
= (struct grouphead
*)scalloc(1, sizeof *gh
);
729 gh
->g_name
= sstrdup(gname
);
731 gh
->g_link
= groups
[h
];
736 * Insert names from the command list into the group.
737 * Who cares if there are duplicates? They get tossed
741 for (ap
= argv
+1; *ap
!= NULL
; ap
++) {
742 gp
= (struct group
*)scalloc(1, sizeof *gp
);
743 gp
->ge_name
= sstrdup(*ap
);
744 gp
->ge_link
= gh
->g_list
;
751 * Delete the passed groups.
759 fprintf(stderr
, tr(209, "Must specify alias to remove\n"));
764 while (*++argv
!= NULL
);
769 * Sort the passed string vecotor into ascending dictionary
777 for (ap
= list
; *ap
!= NULL
; ap
++)
781 qsort(list
, ap
-list
, sizeof(*list
), diction
);
785 * Do a dictionary order comparison of the arguments from
789 diction(const void *a
, const void *b
)
791 return(strcmp(*(char**)UNCONST(a
), *(char**)UNCONST(b
)));
795 * Change to another file. With no argument, print information about
810 fprintf(stderr
, tr(516,
811 "Cannot change folder from within a hook.\n"));
815 save_mbox_for_possible_quitstuff();
817 i
= setfile(*argv
, 0);
820 callhook(mailname
, 0);
821 if (i
> 0 && value("emptystart") == NULL
)
823 announce(value("bsdcompat") != NULL
|| value("bsdannounce") != NULL
);
828 * Expand file names like echo
833 char const **argv
= v
, **ap
, *cp
;
836 for (ap
= argv
; *ap
!= NULL
; ++ap
) {
838 if ((cp
= fexpand(cp
, FEXP_NSHORTCUT
)) != NULL
) {
842 while (*cp
!= '\0' &&
843 (c
= expand_shell_escape(&cp
, FAL0
))
846 /* \c ends overall processing */
859 return (respond_or_Respond('R'))((int *)v
, 0);
865 return (respond_or_Respond('R'))((int *)v
, 1);
869 * Reply to a series of messages by simply mailing to the senders
870 * and not messing around with the To: and Cc: lists as in normal
874 Respond_internal(int *msgvec
, int recipient_record
)
880 enum gfield gf
= boption("fullnames") ? GFULL
: GSKIN
;
882 memset(&head
, 0, sizeof head
);
884 for (ap
= msgvec
; *ap
!= 0; ap
++) {
885 mp
= &message
[*ap
- 1];
888 if ((cp
= hfield1("reply-to", mp
)) == NULL
)
889 if ((cp
= hfield1("from", mp
)) == NULL
)
891 head
.h_to
= cat(head
.h_to
, lextract(cp
, GTO
| gf
));
893 if (head
.h_to
== NULL
)
896 mp
= &message
[msgvec
[0] - 1];
897 head
.h_subject
= hfield1("subject", mp
);
898 head
.h_subject
= _reedit(head
.h_subject
);
899 make_ref_and_cs(mp
, &head
);
901 if (boption("quote-as-attachment")) {
902 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
903 head
.h_attach
->a_msgno
= *msgvec
;
904 head
.h_attach
->a_content_description
= tr(512,
905 "Original message content");
908 if (mail1(&head
, 1, mp
, NULL
, recipient_record
, 0) == OKAY
&&
909 value("markanswered") && (mp
->m_flag
& MANSWERED
) == 0)
910 mp
->m_flag
|= MANSWER
| MANSWERED
;
915 * Conditional commands. These allow one to parameterize one's
916 * .mailrc and do some things if sending, others if receiving.
925 printf(tr(42, "Illegal nested \"if\"\n"));
944 printf(tr(43, "Unrecognized if-keyword: \"%s\"\n"), cp
);
951 * Implement 'else'. This is pretty simple -- we just
952 * flip over the conditional flag.
962 printf(tr(44, "\"Else\" without matching \"if\"\n"));
978 printf(tr(45, "Mail's idea of conditions is screwed up\n"));
986 * End of if statement. Just set cond back to anything.
995 printf(tr(46, "\"Endif\" without matching \"if\"\n"));
1003 * Set the list of alternate names.
1009 char **namelist
= v
, **ap
, **ap2
, *cp
;
1011 l
= argcount(namelist
) + 1;
1014 if (altnames
== NULL
)
1016 for (ap
= altnames
; *ap
!= NULL
; ++ap
)
1022 if (altnames
!= NULL
) {
1023 for (ap
= altnames
; *ap
!= NULL
; ++ap
)
1027 altnames
= smalloc(l
* sizeof(char*));
1028 for (ap
= namelist
, ap2
= altnames
; *ap
; ++ap
, ++ap2
) {
1029 l
= strlen(*ap
) + 1;
1040 * Do the real work of resending.
1043 resend1(void *v
, int add_resent
)
1053 msgvec
= (int *)salloc((msgCount
+ 2) * sizeof *msgvec
);
1054 name
= laststring(str
, &f
, 1);
1056 puts(tr(47, "No recipient specified."));
1060 *msgvec
= first(0, MMNORM
);
1064 puts(tr(48, "No applicable messages."));
1068 } else if (getmsglist(str
, msgvec
, 0) < 0)
1073 printf("No applicable messages.\n");
1076 sn
= nalloc(name
, GTO
);
1077 to
= usermap(sn
, FAL0
);
1078 for (ip
= msgvec
; *ip
&& ip
- msgvec
< msgCount
; ip
++) {
1079 if (resend_msg(&message
[*ip
- 1], to
, add_resent
) != OKAY
)
1086 * Resend a message list to a third person.
1091 return resend1(v
, 1);
1095 * Resend a message list to a third person without adding headers.
1100 return resend1(v
, 0);
1104 * 'newmail' or 'inc' command: Check for new mail without writing old
1116 (mb
.mb_type
!= MB_IMAP
|| imap_newmail(1)) &&
1118 (val
= setfile(mailname
, 1)) == 0) {
1120 setdot(&message
[mdot
- 1]);
1126 list_shortcuts(void)
1130 for (s
= shortcuts
; s
; s
= s
->sh_next
)
1131 printf("%s=%s\n", s
->sh_short
, s
->sh_long
);
1137 char **args
= (char **)v
;
1140 if (args
[0] == NULL
) {
1144 if (args
[1] == NULL
) {
1145 fprintf(stderr
, tr(220,
1146 "expansion name for shortcut missing\n"));
1149 if (args
[2] != NULL
) {
1150 fprintf(stderr
, tr(221, "too many arguments\n"));
1153 if ((s
= get_shortcut(args
[0])) != NULL
) {
1155 s
->sh_long
= sstrdup(args
[1]);
1157 s
= scalloc(1, sizeof *s
);
1158 s
->sh_short
= sstrdup(args
[0]);
1159 s
->sh_long
= sstrdup(args
[1]);
1160 s
->sh_next
= shortcuts
;
1166 FL
struct shortcut
*
1167 get_shortcut(const char *str
)
1171 for (s
= shortcuts
; s
; s
= s
->sh_next
)
1172 if (strcmp(str
, s
->sh_short
) == 0)
1178 delete_shortcut(const char *str
)
1180 struct shortcut
*sp
, *sq
;
1182 for (sp
= shortcuts
, sq
= NULL
; sp
; sq
= sp
, sp
= sp
->sh_next
) {
1183 if (strcmp(sp
->sh_short
, str
) == 0) {
1187 sq
->sh_next
= sp
->sh_next
;
1188 if (sp
== shortcuts
)
1189 shortcuts
= sp
->sh_next
;
1200 char **args
= (char **)v
;
1203 if (args
[0] == NULL
) {
1204 fprintf(stderr
, tr(222, "need shortcut names to remove\n"));
1207 while (*args
!= NULL
) {
1208 if (delete_shortcut(*args
) != OKAY
) {
1210 fprintf(stderr
, tr(223, "%s: no such shortcut\n"),
1225 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1226 m
= &message
[*ip
-1];
1228 if ((m
->m_flag
& (MFLAG
|MFLAGGED
)) == 0)
1229 m
->m_flag
|= MFLAG
|MFLAGGED
;
1241 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1242 m
= &message
[*ip
-1];
1244 if (m
->m_flag
& (MFLAG
|MFLAGGED
)) {
1245 m
->m_flag
&= ~(MFLAG
|MFLAGGED
);
1246 m
->m_flag
|= MUNFLAG
;
1259 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1260 m
= &message
[*ip
-1];
1262 if ((m
->m_flag
& (MANSWER
|MANSWERED
)) == 0)
1263 m
->m_flag
|= MANSWER
|MANSWERED
;
1269 cunanswered(void *v
)
1275 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1276 m
= &message
[*ip
-1];
1278 if (m
->m_flag
& (MANSWER
|MANSWERED
)) {
1279 m
->m_flag
&= ~(MANSWER
|MANSWERED
);
1280 m
->m_flag
|= MUNANSWER
;
1293 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1294 m
= &message
[*ip
-1];
1296 if ((m
->m_flag
& (MDRAFT
|MDRAFTED
)) == 0)
1297 m
->m_flag
|= MDRAFT
|MDRAFTED
;
1309 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1310 m
= &message
[*ip
-1];
1312 if (m
->m_flag
& (MDRAFT
|MDRAFTED
)) {
1313 m
->m_flag
&= ~(MDRAFT
|MDRAFTED
);
1314 m
->m_flag
|= MUNDRAFT
;
1326 switch (mb
.mb_type
) {
1332 return (ccmdnotsupp(NULL
));
1339 return (ccmdnotsupp(NULL
));
1355 if (*args
== NULL
) {
1356 fprintf(stderr
, tr(290, "Syntax is: remove mailbox ...\n"));
1360 if ((name
= expand(*args
)) == NULL
)
1362 if (strcmp(name
, mailname
) == 0) {
1363 fprintf(stderr
, tr(286,
1364 "Cannot remove current mailbox \"%s\".\n"),
1369 snprintf(vb
, sizeof vb
, tr(287, "Remove \"%s\" (y/n) ? "),
1373 switch (which_protocol(name
)) {
1375 if (unlink(name
) < 0) { /* do not handle .gz .bz2 */
1381 fprintf(stderr
, tr(288,
1382 "Cannot remove POP3 mailbox \"%s\".\n"),
1388 if (imap_remove(name
) != OKAY
)
1393 if (maildir_remove(name
) != OKAY
)
1397 fprintf(stderr
, tr(289,
1398 "Unknown protocol in \"%s\". Not removed.\n"),
1409 char **args
= v
, *old
, *new;
1410 enum protocol oldp
, newp
;
1413 if (args
[0] == NULL
|| args
[1] == NULL
|| args
[2] != NULL
) {
1414 fprintf(stderr
, "Syntax: rename old new\n");
1418 if ((old
= expand(args
[0])) == NULL
)
1420 oldp
= which_protocol(old
);
1421 if ((new = expand(args
[1])) == NULL
)
1423 newp
= which_protocol(new);
1425 if (strcmp(old
, mailname
) == 0 || strcmp(new, mailname
) == 0) {
1426 fprintf(stderr
, tr(291,
1427 "Cannot rename current mailbox \"%s\".\n"), old
);
1430 if ((oldp
== PROTO_IMAP
|| newp
== PROTO_IMAP
) && oldp
!= newp
) {
1431 fprintf(stderr
, tr(292,
1432 "Can only rename folders of same type.\n"));
1435 if (newp
== PROTO_POP3
)
1439 if (link(old
, new) < 0) {
1453 } else if (unlink(old
) < 0) {
1459 if (rename(old
, new) < 0) {
1465 nopop3
: fprintf(stderr
, tr(293, "Cannot rename POP3 mailboxes.\n"));
1470 if (imap_rename(old
, new) != OKAY
)
1476 fprintf(stderr
, tr(294,
1477 "Unknown protocol in \"%s\" and \"%s\". "
1478 "Not renamed.\n"), old
, new);