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
= ok_vlook(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
= ok_vlook(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
= ok_blook(bang
);
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 (ok_blook(reply_in_same_charset
) &&
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
+= ok_blook(Replyall
);
328 opt
+= ok_blook(flipr
);
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
= ok_blook(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 (!ok_blook(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 (ok_blook(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 (ok_blook(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 ok_blook(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
= ok_blook(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
| (ok_blook(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
+= _var_vokclear(&varbuf
[2]);
671 errs
+= _var_vokset(varbuf
, (uintptr_t)cp
);
680 * Unset a bunch of variable values.
689 for (ap
= (char**)v
; *ap
!= NULL
; ap
++)
690 errs
+= _var_vokclear(*ap
);
695 * Put add users to a group.
701 struct grouphead
*gh
;
705 char **ap
, *gname
, **p
;
708 for (h
= 0, s
= 1; h
< HSHSIZE
; h
++)
709 for (gh
= groups
[h
]; gh
!= NULL
; gh
= gh
->g_link
)
712 ap
= (char **)salloc(s
* sizeof *ap
);
713 for (h
= 0, p
= ap
; h
< HSHSIZE
; h
++)
714 for (gh
= groups
[h
]; gh
!= NULL
; gh
= gh
->g_link
)
718 for (p
= ap
; *p
!= NULL
; p
++)
722 if (argv
[1] == NULL
) {
728 if ((gh
= findgroup(gname
)) == NULL
) {
729 gh
= (struct grouphead
*)scalloc(1, sizeof *gh
);
730 gh
->g_name
= sstrdup(gname
);
732 gh
->g_link
= groups
[h
];
737 * Insert names from the command list into the group.
738 * Who cares if there are duplicates? They get tossed
742 for (ap
= argv
+1; *ap
!= NULL
; ap
++) {
743 gp
= (struct group
*)scalloc(1, sizeof *gp
);
744 gp
->ge_name
= sstrdup(*ap
);
745 gp
->ge_link
= gh
->g_list
;
752 * Delete the passed groups.
760 fprintf(stderr
, tr(209, "Must specify alias to remove\n"));
765 while (*++argv
!= NULL
);
770 * Sort the passed string vecotor into ascending dictionary
778 for (ap
= list
; *ap
!= NULL
; ap
++)
782 qsort(list
, ap
-list
, sizeof(*list
), diction
);
786 * Do a dictionary order comparison of the arguments from
790 diction(const void *a
, const void *b
)
792 return(strcmp(*(char**)UNCONST(a
), *(char**)UNCONST(b
)));
796 * Change to another file. With no argument, print information about
811 fprintf(stderr
, tr(516,
812 "Cannot change folder from within a hook.\n"));
816 save_mbox_for_possible_quitstuff();
818 i
= setfile(*argv
, 0);
821 callhook(mailname
, 0);
822 if (i
> 0 && !ok_blook(emptystart
))
824 announce(ok_blook(bsdcompat
) || ok_blook(bsdannounce
));
829 * Expand file names like echo
834 char const **argv
= v
, **ap
, *cp
;
837 for (ap
= argv
; *ap
!= NULL
; ++ap
) {
839 if ((cp
= fexpand(cp
, FEXP_NSHORTCUT
)) != NULL
) {
843 while (*cp
!= '\0' &&
844 (c
= expand_shell_escape(&cp
, FAL0
))
847 /* \c ends overall processing */
860 return (respond_or_Respond('R'))((int *)v
, 0);
866 return (respond_or_Respond('R'))((int *)v
, 1);
870 * Reply to a series of messages by simply mailing to the senders
871 * and not messing around with the To: and Cc: lists as in normal
875 Respond_internal(int *msgvec
, int recipient_record
)
881 enum gfield gf
= ok_blook(fullnames
) ? GFULL
: GSKIN
;
883 memset(&head
, 0, sizeof head
);
885 for (ap
= msgvec
; *ap
!= 0; ap
++) {
886 mp
= &message
[*ap
- 1];
889 if ((cp
= hfield1("reply-to", mp
)) == NULL
)
890 if ((cp
= hfield1("from", mp
)) == NULL
)
892 head
.h_to
= cat(head
.h_to
, lextract(cp
, GTO
| gf
));
894 if (head
.h_to
== NULL
)
897 mp
= &message
[msgvec
[0] - 1];
898 head
.h_subject
= hfield1("subject", mp
);
899 head
.h_subject
= _reedit(head
.h_subject
);
900 make_ref_and_cs(mp
, &head
);
902 if (ok_blook(quote_as_attachment
)) {
903 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
904 head
.h_attach
->a_msgno
= *msgvec
;
905 head
.h_attach
->a_content_description
= tr(512,
906 "Original message content");
909 if (mail1(&head
, 1, mp
, NULL
, recipient_record
, 0) == OKAY
&&
910 ok_blook(markanswered
) && (mp
->m_flag
& MANSWERED
) == 0)
911 mp
->m_flag
|= MANSWER
| MANSWERED
;
916 * Conditional commands. These allow one to parameterize one's
917 * .mailrc and do some things if sending, others if receiving.
926 printf(tr(42, "Illegal nested \"if\"\n"));
945 printf(tr(43, "Unrecognized if-keyword: \"%s\"\n"), cp
);
952 * Implement 'else'. This is pretty simple -- we just
953 * flip over the conditional flag.
963 printf(tr(44, "\"Else\" without matching \"if\"\n"));
979 printf(tr(45, "Mail's idea of conditions is screwed up\n"));
987 * End of if statement. Just set cond back to anything.
996 printf(tr(46, "\"Endif\" without matching \"if\"\n"));
1004 * Set the list of alternate names.
1010 char **namelist
= v
, **ap
, **ap2
, *cp
;
1012 l
= argcount(namelist
) + 1;
1015 if (altnames
== NULL
)
1017 for (ap
= altnames
; *ap
!= NULL
; ++ap
)
1023 if (altnames
!= NULL
) {
1024 for (ap
= altnames
; *ap
!= NULL
; ++ap
)
1028 altnames
= smalloc(l
* sizeof(char*));
1029 for (ap
= namelist
, ap2
= altnames
; *ap
; ++ap
, ++ap2
) {
1030 l
= strlen(*ap
) + 1;
1041 * Do the real work of resending.
1044 resend1(void *v
, int add_resent
)
1054 msgvec
= (int *)salloc((msgCount
+ 2) * sizeof *msgvec
);
1055 name
= laststring(str
, &f
, 1);
1057 puts(tr(47, "No recipient specified."));
1061 *msgvec
= first(0, MMNORM
);
1065 puts(tr(48, "No applicable messages."));
1069 } else if (getmsglist(str
, msgvec
, 0) < 0)
1074 printf("No applicable messages.\n");
1077 sn
= nalloc(name
, GTO
);
1078 to
= usermap(sn
, FAL0
);
1079 for (ip
= msgvec
; *ip
&& ip
- msgvec
< msgCount
; ip
++) {
1080 if (resend_msg(&message
[*ip
- 1], to
, add_resent
) != OKAY
)
1087 * Resend a message list to a third person.
1092 return resend1(v
, 1);
1096 * Resend a message list to a third person without adding headers.
1101 return resend1(v
, 0);
1105 * 'newmail' or 'inc' command: Check for new mail without writing old
1117 (mb
.mb_type
!= MB_IMAP
|| imap_newmail(1)) &&
1119 (val
= setfile(mailname
, 1)) == 0) {
1121 setdot(&message
[mdot
- 1]);
1127 list_shortcuts(void)
1131 for (s
= shortcuts
; s
; s
= s
->sh_next
)
1132 printf("%s=%s\n", s
->sh_short
, s
->sh_long
);
1138 char **args
= (char **)v
;
1141 if (args
[0] == NULL
) {
1145 if (args
[1] == NULL
) {
1146 fprintf(stderr
, tr(220,
1147 "expansion name for shortcut missing\n"));
1150 if (args
[2] != NULL
) {
1151 fprintf(stderr
, tr(221, "too many arguments\n"));
1154 if ((s
= get_shortcut(args
[0])) != NULL
) {
1156 s
->sh_long
= sstrdup(args
[1]);
1158 s
= scalloc(1, sizeof *s
);
1159 s
->sh_short
= sstrdup(args
[0]);
1160 s
->sh_long
= sstrdup(args
[1]);
1161 s
->sh_next
= shortcuts
;
1167 FL
struct shortcut
*
1168 get_shortcut(const char *str
)
1172 for (s
= shortcuts
; s
; s
= s
->sh_next
)
1173 if (strcmp(str
, s
->sh_short
) == 0)
1179 delete_shortcut(const char *str
)
1181 struct shortcut
*sp
, *sq
;
1183 for (sp
= shortcuts
, sq
= NULL
; sp
; sq
= sp
, sp
= sp
->sh_next
) {
1184 if (strcmp(sp
->sh_short
, str
) == 0) {
1188 sq
->sh_next
= sp
->sh_next
;
1189 if (sp
== shortcuts
)
1190 shortcuts
= sp
->sh_next
;
1201 char **args
= (char **)v
;
1204 if (args
[0] == NULL
) {
1205 fprintf(stderr
, tr(222, "need shortcut names to remove\n"));
1208 while (*args
!= NULL
) {
1209 if (delete_shortcut(*args
) != OKAY
) {
1211 fprintf(stderr
, tr(223, "%s: no such shortcut\n"),
1226 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1227 m
= &message
[*ip
-1];
1229 if ((m
->m_flag
& (MFLAG
|MFLAGGED
)) == 0)
1230 m
->m_flag
|= MFLAG
|MFLAGGED
;
1242 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1243 m
= &message
[*ip
-1];
1245 if (m
->m_flag
& (MFLAG
|MFLAGGED
)) {
1246 m
->m_flag
&= ~(MFLAG
|MFLAGGED
);
1247 m
->m_flag
|= MUNFLAG
;
1260 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1261 m
= &message
[*ip
-1];
1263 if ((m
->m_flag
& (MANSWER
|MANSWERED
)) == 0)
1264 m
->m_flag
|= MANSWER
|MANSWERED
;
1270 cunanswered(void *v
)
1276 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1277 m
= &message
[*ip
-1];
1279 if (m
->m_flag
& (MANSWER
|MANSWERED
)) {
1280 m
->m_flag
&= ~(MANSWER
|MANSWERED
);
1281 m
->m_flag
|= MUNANSWER
;
1294 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1295 m
= &message
[*ip
-1];
1297 if ((m
->m_flag
& (MDRAFT
|MDRAFTED
)) == 0)
1298 m
->m_flag
|= MDRAFT
|MDRAFTED
;
1310 for (ip
= msgvec
; *ip
!= 0; ip
++) {
1311 m
= &message
[*ip
-1];
1313 if (m
->m_flag
& (MDRAFT
|MDRAFTED
)) {
1314 m
->m_flag
&= ~(MDRAFT
|MDRAFTED
);
1315 m
->m_flag
|= MUNDRAFT
;
1327 switch (mb
.mb_type
) {
1333 return (ccmdnotsupp(NULL
));
1340 return (ccmdnotsupp(NULL
));
1356 if (*args
== NULL
) {
1357 fprintf(stderr
, tr(290, "Syntax is: remove mailbox ...\n"));
1361 if ((name
= expand(*args
)) == NULL
)
1363 if (strcmp(name
, mailname
) == 0) {
1364 fprintf(stderr
, tr(286,
1365 "Cannot remove current mailbox \"%s\".\n"),
1370 snprintf(vb
, sizeof vb
, tr(287, "Remove \"%s\" (y/n) ? "),
1374 switch (which_protocol(name
)) {
1376 if (unlink(name
) < 0) { /* do not handle .gz .bz2 */
1382 fprintf(stderr
, tr(288,
1383 "Cannot remove POP3 mailbox \"%s\".\n"),
1389 if (imap_remove(name
) != OKAY
)
1394 if (maildir_remove(name
) != OKAY
)
1398 fprintf(stderr
, tr(289,
1399 "Unknown protocol in \"%s\". Not removed.\n"),
1410 char **args
= v
, *old
, *new;
1411 enum protocol oldp
, newp
;
1414 if (args
[0] == NULL
|| args
[1] == NULL
|| args
[2] != NULL
) {
1415 fprintf(stderr
, "Syntax: rename old new\n");
1419 if ((old
= expand(args
[0])) == NULL
)
1421 oldp
= which_protocol(old
);
1422 if ((new = expand(args
[1])) == NULL
)
1424 newp
= which_protocol(new);
1426 if (strcmp(old
, mailname
) == 0 || strcmp(new, mailname
) == 0) {
1427 fprintf(stderr
, tr(291,
1428 "Cannot rename current mailbox \"%s\".\n"), old
);
1431 if ((oldp
== PROTO_IMAP
|| newp
== PROTO_IMAP
) && oldp
!= newp
) {
1432 fprintf(stderr
, tr(292,
1433 "Can only rename folders of same type.\n"));
1436 if (newp
== PROTO_POP3
)
1440 if (link(old
, new) < 0) {
1454 } else if (unlink(old
) < 0) {
1460 if (rename(old
, new) < 0) {
1466 nopop3
: fprintf(stderr
, tr(293, "Cannot rename POP3 mailboxes.\n"));
1471 if (imap_rename(old
, new) != OKAY
)
1477 fprintf(stderr
, tr(294,
1478 "Unknown protocol in \"%s\" and \"%s\". "
1479 "Not renamed.\n"), old
, new);