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 - 2016 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
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. 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
38 #ifndef HAVE_AMALGAMATION
42 static char *_bang_buf
;
43 static size_t _bang_size
;
45 /* Modify subject we reply to to begin with Re: if it does not already */
46 static char * _reedit(char *subj
);
48 /* Expand the shell escape by expanding unescaped !'s into the last issued
49 * command where possible */
50 static void _bangexp(char **str
, size_t *size
);
52 static void make_ref_and_cs(struct message
*mp
, struct header
*head
);
54 /* `reply' and `Lreply' workhorse */
55 static int _list_reply(int *msgvec
, enum header_flags hf
);
57 /* Get PTF to implementation of command c (i.e., take care for *flipr*) */
58 static int (* _reply_or_Reply(char c
))(int *, bool_t
);
60 /* Reply to a single message. Extract each name from the message header and
61 * send them off to mail1() */
62 static int _reply(int *msgvec
, bool_t recipient_record
);
64 /* Reply to a series of messages by simply mailing to the senders and not
65 * messing around with the To: and Cc: lists as in normal reply */
66 static int _Reply(int *msgvec
, bool_t recipient_record
);
68 /* Forward a message to a new recipient, in the sense of RFC 2822 */
69 static int _fwd(char *str
, int recipient_record
);
71 /* Modify the subject we are replying to to begin with Fwd: */
72 static char * __fwdedit(char *subj
);
74 /* Do the real work of resending */
75 static int _resend1(void *v
, bool_t add_resent
);
78 static int _c_file(void *v
, enum fedit_mode fm
);
87 if (subj
== NULL
|| *subj
== '\0')
92 mime_fromhdr(&in
, &out
, TD_ISPR
| TD_ICONV
);
94 if ((newsubj
= subject_re_trim(out
.s
)) != out
.s
)
95 newsubj
= savestr(out
.s
);
97 /* RFC mandates english "Re: " */
98 newsubj
= salloc(out
.l
+ 4 +1);
99 sstpcpy(sstpcpy(newsubj
, "Re: "), out
.s
);
109 _bangexp(char **str
, size_t *size
)
114 size_t sz
, i
, j
, bangbufsize
;
117 dobang
= ok_blook(bang
);
119 bangbuf
= smalloc(bangbufsize
= *size
);
123 if ((*str
)[i
] == '!') {
124 sz
= strlen(_bang_buf
);
125 bangbuf
= srealloc(bangbuf
, bangbufsize
+= sz
);
127 memcpy(bangbuf
+ j
, _bang_buf
, sz
+ 1);
133 if ((*str
)[i
] == '\\' && (*str
)[i
+ 1] == '!') {
138 bangbuf
[j
++] = (*str
)[i
++];
142 printf("!%s\n", bangbuf
);
147 *str
= srealloc(*str
, *size
= sz
);
148 memcpy(*str
, bangbuf
, sz
);
150 _bang_buf
= srealloc(_bang_buf
, _bang_size
= sz
);
151 memcpy(_bang_buf
, bangbuf
, sz
);
157 make_ref_and_cs(struct message
*mp
, struct header
*head
) /* TODO rewrite FAST */
159 char *oldref
, *oldmsgid
, *newref
, *cp
;
160 size_t oldreflen
= 0, oldmsgidlen
= 0, reflen
;
165 oldref
= hfield1("references", mp
);
166 oldmsgid
= hfield1("message-id", mp
);
167 if (oldmsgid
== NULL
|| *oldmsgid
== '\0') {
174 oldreflen
= strlen(oldref
);
175 reflen
+= oldreflen
+ 2;
178 oldmsgidlen
= strlen(oldmsgid
);
179 reflen
+= oldmsgidlen
;
182 newref
= smalloc(reflen
);
183 if (oldref
!= NULL
) {
184 memcpy(newref
, oldref
, oldreflen
+1);
185 if (oldmsgid
!= NULL
) {
186 newref
[oldreflen
++] = ',';
187 newref
[oldreflen
++] = ' ';
188 memcpy(newref
+ oldreflen
, oldmsgid
, oldmsgidlen
+1);
191 memcpy(newref
, oldmsgid
, oldmsgidlen
+1);
192 n
= extract(newref
, GREF
);
195 /* Limit number of references TODO better on parser side */
196 while (n
->n_flink
!= NULL
)
198 for (i
= 1; i
<= REFERENCES_MAX
; ++i
) {
199 if (n
->n_blink
!= NULL
)
206 if (ok_blook(reply_in_same_charset
) &&
207 (cp
= hfield1("content-type", mp
)) != NULL
)
208 head
->h_charset
= mime_param_get("charset", cp
);
214 _list_reply(int *msgvec
, enum header_flags hf
)
218 char const *reply_to
, *rcv
, *cp
;
220 struct name
*rt
, *mft
, *np
;
224 /* TODO Since we may recur and do stuff with message lists we need to save
225 * TODO away the argument vector as long as that isn't done by machinery */
228 for (i
= 0; msgvec
[i
] != 0; ++i
)
231 save_msgvec
= ac_alloc(sizeof(*save_msgvec
) * i
);
233 save_msgvec
[i
] = msgvec
[i
];
234 msgvec
= save_msgvec
;
238 mp
= message
+ *msgvec
- 1;
242 memset(&head
, 0, sizeof head
);
245 head
.h_subject
= _reedit(hfield1("subject", mp
));
246 gf
= ok_blook(fullnames
) ? GFULL
: GSKIN
;
250 if ((reply_to
= hfield1("reply-to", mp
)) != NULL
&&
251 (cp
= ok_vlook(reply_to_honour
)) != NULL
&&
252 (rt
= checkaddrs(lextract(reply_to
, GTO
| gf
), EACM_STRICT
, NULL
)
254 char const *tr
= _("Reply-To %s%s");
255 size_t l
= strlen(tr
) + strlen(rt
->n_name
) + 3 +1;
256 char *sp
= salloc(l
);
258 snprintf(sp
, l
, tr
, rt
->n_name
, (rt
->n_flink
!= NULL
? "..." : ""));
259 if (quadify(cp
, UIZ_MAX
, sp
, TRU1
) > FAL0
)
263 if (rcv
== NULL
&& (rcv
= hfield1("from", mp
)) == NULL
)
268 if (ok_blook(recipients_in_cc
) && (cp
= hfield1("to", mp
)) != NULL
)
269 np
= lextract(cp
, GCC
| gf
);
270 if ((cp
= hfield1("cc", mp
)) != NULL
)
271 np
= cat(np
, lextract(cp
, GCC
| gf
));
273 head
.h_cc
= delete_alternates(np
);
278 np
= (rcv
== reply_to
) ? namelist_dup(rt
, GTO
| gf
)
279 : lextract(rcv
, GTO
| gf
);
280 if (!ok_blook(recipients_in_cc
) && (cp
= hfield1("to", mp
)) != NULL
)
281 np
= cat(np
, lextract(cp
, GTO
| gf
));
282 /* Delete my name from reply list, and with it, all my alternate names */
283 np
= delete_alternates(np
);
285 np
= lextract(rcv
, GTO
| gf
);
288 /* The user may have send this to himself, don't ignore that */
289 namelist_vaporise_head(&head
, EACM_NORMAL
, FAL0
, NULL
);
290 if (head
.h_to
== NULL
)
293 /* Mail-Followup-To: */
295 if (ok_vlook(followup_to_honour
) != NULL
&&
296 (cp
= hfield1("mail-followup-to", mp
)) != NULL
&&
297 (mft
= np
= checkaddrs(lextract(cp
, GTO
| gf
), EACM_STRICT
, NULL
)
299 char const *tr
= _("Followup-To %s%s");
300 size_t l
= strlen(tr
) + strlen(np
->n_name
) + 3 +1;
301 char *sp
= salloc(l
);
303 snprintf(sp
, l
, tr
, np
->n_name
, (np
->n_flink
!= NULL
? "..." : ""));
304 if (quadify(ok_vlook(followup_to_honour
), UIZ_MAX
, sp
, TRU1
) > FAL0
) {
308 mft
= namelist_vaporise_head(&head
, EACM_STRICT
, FAL0
, NULL
);
313 /* Special massage for list (follow-up) messages */
314 if (mft
!= NULL
|| (hf
& HF_LIST_REPLY
) || ok_blook(followup_to
)) {
315 /* Learn about a possibly sending mailing list; use do for break; */
316 if ((cp
= hfield1("list-post", mp
)) != NULL
) do {
319 if ((x
= lextract(cp
, GEXTRA
| GSKIN
)) == NULL
|| x
->n_flink
!= NULL
||
320 (cp
= url_mailto_to_address(x
->n_name
)) == NULL
||
321 /* XXX terribly wasteful to create a new name, and can't we find
322 * XXX a way to mitigate that?? */
323 is_addr_invalid(x
= nalloc(cp
, GEXTRA
| GSKIN
), EACM_STRICT
)) {
324 if (options
& OPT_D_V
)
325 n_err(_("Message contains invalid List-Post: header\n"));
331 /* A special case has been seen on e.g. ietf-announce@ietf.org:
332 * these usually post to multiple groups, with ietf-announce@
333 * in List-Post:, but with Reply-To: set to ietf@ietf.org (since
334 * -announce@ is only used for announcements, say).
335 * So our desire is to honour this request and actively overwrite
336 * List-Post: for our purpose; but only if its a single address.
337 * However, to avoid ambiguities with users that place themselve in
338 * Reply-To: and mailing lists which don't overwrite this (or only
339 * extend this, shall such exist), only do so if reply_to exists of
340 * a single address which points to the same domain as List-Post: */
341 if (reply_to
!= NULL
&& rt
->n_flink
== NULL
&&
342 name_is_same_domain(x
, rt
))
343 cp
= rt
->n_name
; /* rt is EACM_STRICT tested */
345 /* "Automatically `mlist'" the List-Post: address temporarily */
346 if (is_mlist(cp
, FAL0
) == MLIST_OTHER
)
347 head
.h_list_post
= cp
;
352 /* In case of list replies we actively sort out any non-list recipient,
353 * but _only_ if we did not honour a MFT:, assuming that members of MFT
354 * were there for a reason; cp is still List-Post:/eqivalent */
355 if ((hf
& HF_LIST_REPLY
) && mft
== NULL
) {
356 struct name
*nhp
= head
.h_to
;
359 while (nhp
!= NULL
) {
363 if ((cp
!= NULL
&& !asccasecmp(cp
, np
->n_name
)) ||
364 is_mlist(np
->n_name
, FAL0
) != MLIST_OTHER
) {
365 np
->n_type
= (np
->n_type
& ~GMASK
) | GTO
;
366 np
->n_flink
= head
.h_to
;
370 if ((nhp
= head
.h_cc
) != NULL
) {
377 make_ref_and_cs(mp
, &head
);
379 if (ok_blook(quote_as_attachment
)) {
380 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
381 head
.h_attach
->a_msgno
= *msgvec
;
382 head
.h_attach
->a_content_description
= _("Original message content");
385 if (mail1(&head
, 1, mp
, NULL
, !!(hf
& HF_RECIPIENT_RECORD
), 0) == OKAY
&&
386 ok_blook(markanswered
) && !(mp
->m_flag
& MANSWERED
))
387 mp
->m_flag
|= MANSWER
| MANSWERED
;
389 if (*++msgvec
!= 0) {
390 /* TODO message (error) ring.., less sleep */
391 printf(_("Waiting a second before proceeding to the next message..\n"));
393 n_msleep(1000, FAL0
);
397 ac_free(save_msgvec
);
403 (*_reply_or_Reply(char c
))(int *, bool_t
)
405 int (*rv
)(int*, bool_t
);
408 rv
= (ok_blook(flipr
) ^ (c
== 'R')) ? &_Reply
: &_reply
;
414 _reply(int *msgvec
, bool_t recipient_record
)
419 rv
= _list_reply(msgvec
, recipient_record
? HF_RECIPIENT_RECORD
: HF_NONE
);
425 _Reply(int *msgvec
, bool_t recipient_record
)
434 memset(&head
, 0, sizeof head
);
435 gf
= ok_blook(fullnames
) ? GFULL
: GSKIN
;
437 for (ap
= msgvec
; *ap
!= 0; ++ap
) {
441 mp
= message
+ *ap
- 1;
445 if ((rp
= hfield1("reply-to", mp
)) != NULL
&&
446 (cp
= ok_vlook(reply_to_honour
)) != NULL
&&
447 (rt
= checkaddrs(lextract(rp
, GTO
| gf
), EACM_STRICT
, NULL
)
449 char const *tr
= _("Reply-To %s%s");
450 size_t l
= strlen(tr
) + strlen(rt
->n_name
) + 3 +1;
451 char *sp
= salloc(l
);
453 snprintf(sp
, l
, tr
, rt
->n_name
, (rt
->n_flink
!= NULL
? "..." : ""));
454 if (quadify(cp
, UIZ_MAX
, sp
, TRU1
) > FAL0
) {
455 head
.h_to
= cat(head
.h_to
, rt
);
460 if ((cp
= hfield1("from", mp
)) == NULL
)
462 head
.h_to
= cat(head
.h_to
, lextract(cp
, GTO
| gf
));
464 if (head
.h_to
== NULL
)
467 mp
= message
+ msgvec
[0] - 1;
468 head
.h_subject
= hfield1("subject", mp
);
469 head
.h_subject
= _reedit(head
.h_subject
);
470 make_ref_and_cs(mp
, &head
);
472 if (ok_blook(quote_as_attachment
)) {
473 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
474 head
.h_attach
->a_msgno
= *msgvec
;
475 head
.h_attach
->a_content_description
= _("Original message content");
478 if (mail1(&head
, 1, mp
, NULL
, recipient_record
, 0) == OKAY
&&
479 ok_blook(markanswered
) && !(mp
->m_flag
& MANSWERED
))
480 mp
->m_flag
|= MANSWER
| MANSWERED
;
487 _fwd(char *str
, int recipient_record
)
493 bool_t f
, forward_as_attachment
;
496 if ((recipient
= laststring(str
, &f
, TRU1
)) == NULL
) {
497 puts(_("No recipient specified."));
501 forward_as_attachment
= ok_blook(forward_as_attachment
);
502 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
505 *msgvec
= first(0, MMNORM
);
507 if (pstate
& (PS_HOOK_MASK
| PS_ROBOT
)) {
511 printf(_("No messages to forward.\n"));
515 } else if (getmsglist(str
, msgvec
, 0) < 0)
519 if (pstate
& (PS_HOOK_MASK
| PS_ROBOT
)) {
523 printf(_("No applicable messages.\n"));
526 if (msgvec
[1] != 0) {
527 printf(_("Cannot forward multiple messages at once\n"));
531 memset(&head
, 0, sizeof head
);
532 if ((head
.h_to
= lextract(recipient
,
533 (GTO
| (ok_blook(fullnames
) ? GFULL
: GSKIN
)))) == NULL
)
536 mp
= message
+ *msgvec
- 1;
538 if (forward_as_attachment
) {
539 head
.h_attach
= csalloc(1, sizeof *head
.h_attach
);
540 head
.h_attach
->a_msgno
= *msgvec
;
541 head
.h_attach
->a_content_description
= _("Forwarded message");
546 head
.h_subject
= hfield1("subject", mp
);
547 head
.h_subject
= __fwdedit(head
.h_subject
);
548 mail1(&head
, 1, (forward_as_attachment
? NULL
: mp
), NULL
, recipient_record
,
557 __fwdedit(char *subj
)
560 char *newsubj
= NULL
;
563 if (subj
== NULL
|| *subj
== '\0')
568 mime_fromhdr(&in
, &out
, TD_ISPR
| TD_ICONV
);
570 newsubj
= salloc(out
.l
+ 6);
571 memcpy(newsubj
, "Fwd: ", 5); /* XXX localizable */
572 memcpy(newsubj
+ 5, out
.s
, out
.l
+1);
580 _resend1(void *v
, bool_t add_resent
)
583 struct name
*to
, *sn
;
589 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
590 name
= laststring(str
, &f
, TRU1
);
592 puts(_("No recipient specified."));
597 *msgvec
= first(0, MMNORM
);
599 if (pstate
& (PS_HOOK_MASK
| PS_ROBOT
)) {
603 puts(_("No applicable messages."));
607 } else if (getmsglist(str
, msgvec
, 0) < 0)
611 if (pstate
& (PS_HOOK_MASK
| PS_ROBOT
)) {
615 printf("No applicable messages.\n");
619 sn
= nalloc(name
, GTO
| GSKIN
);
620 to
= usermap(sn
, FAL0
);
621 for (ip
= msgvec
; *ip
!= 0 && UICMP(z
, PTR2SIZE(ip
- msgvec
), <, msgCount
);
623 if (resend_msg(message
+ *ip
- 1, to
, add_resent
) != OKAY
)
632 _c_file(void *v
, enum fedit_mode fm
)
644 if (pstate
& PS_HOOK_MASK
) {
645 n_err(_("Cannot change folder from within a hook\n"));
650 save_mbox_for_possible_quitstuff();
652 i
= setfile(*argv
, fm
);
657 assert(!(fm
& FEDIT_NEWMAIL
)); /* (Prevent implementation error) */
658 if (pstate
& PS_SETFILE_OPENED
)
659 check_folder_hook(FAL0
);
662 /* TODO Don't report "no messages" == 1 == error when we're in, e.g.,
663 * TODO a macro: because that recursed commando loop will terminate the
664 * TODO entire macro due to that! So either the user needs to be able
665 * TODO to react&ignore this "error" (as in "if DOSTUFF" or "DOSTUFF;
666 * TODO if $?", then "overriding an "error"), or we need a different
667 * TODO return that differentiates */
668 i
= (pstate
& PS_ROBOT
) ? 0 : 1;
671 if (pstate
& PS_SETFILE_OPENED
)
672 announce(ok_blook(bsdcompat
) || ok_blook(bsdannounce
));
685 sighandler_type sigint
;
688 cmd
= smalloc(cmdsize
= strlen(str
) +1);
689 memcpy(cmd
, str
, cmdsize
);
690 _bangexp(&cmd
, &cmdsize
);
692 sigint
= safe_signal(SIGINT
, SIG_IGN
);
694 run_command(ok_vlook(SHELL
), &mask
, COMMAND_FD_PASS
, COMMAND_FD_PASS
, "-c",
696 safe_signal(SIGINT
, sigint
);
707 sighandler_type sigint
;
711 sigint
= safe_signal(SIGINT
, SIG_IGN
);
712 run_command(ok_vlook(SHELL
), 0, COMMAND_FD_PASS
, COMMAND_FD_PASS
, NULL
,
714 safe_signal(SIGINT
, sigint
);
723 char buf
[PATH_MAX
]; /* TODO getcwd(3) may return a larger value */
726 if (getcwd(buf
, sizeof buf
) != NULL
) {
730 n_perr(_("getcwd"), 0);
744 if (*arglist
== NULL
)
746 else if ((cp
= file_expand(*arglist
)) == NULL
)
748 if (chdir(cp
) == -1) {
763 rv
= (*_reply_or_Reply('r'))(v
, FAL0
);
774 rv
= _reply(v
, FAL0
);
780 c_replysender(void *v
)
785 rv
= _Reply(v
, FAL0
);
796 rv
= (*_reply_or_Reply('R'))(v
, FAL0
);
807 rv
= _list_reply(v
, HF_LIST_REPLY
);
818 rv
= (*_reply_or_Reply('r'))(v
, TRU1
);
824 c_followupall(void *v
)
829 rv
= _reply(v
, TRU1
);
835 c_followupsender(void *v
)
840 rv
= _Reply(v
, TRU1
);
851 rv
= (*_reply_or_Reply('R'))(v
, TRU1
);
884 rv
= _resend1(v
, TRU1
);
895 rv
= _resend1(v
, FAL0
);
903 int *msgvec
= v
, *ip
, mesg
;
907 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
909 mp
= message
+ mesg
- 1;
910 printf("%d: ", mesg
);
911 if (mp
->m_xlines
> 0)
912 printf("%ld", mp
->m_xlines
);
915 printf("/%lu\n", (ul_i
)mp
->m_xsize
);
927 rv
= _c_file(v
, FEDIT_NONE
);
938 rv
= _c_file(v
, FEDIT_RDONLY
);
945 char const **argv
, **ap
, *cp
;
948 for(ap
= argv
= v
; *ap
!= NULL
; ++ap
){
951 if((cp
= fexpand(*ap
, FEXP_NSHORTCUT
| FEXP_NVAR
)) == NULL
)
967 if ((val
= setfile(mailname
,
968 FEDIT_NEWMAIL
| ((mb
.mb_perm
& MB_DELE
) ? 0 : FEDIT_RDONLY
))
971 setdot(message
+ mdot
- 1);
984 switch (mb
.mb_type
) {
989 rv
= c_cmdnotsupp(NULL
);
1004 char **args
, *name
, *ename
;
1008 if (*(args
= v
) == NULL
) {
1009 n_err(_("Synopsis: remove: <mailbox>...\n"));
1016 fmt
= _("Remove %s");
1017 fmt_len
= strlen(fmt
);
1019 if ((name
= expand(*args
)) == NULL
)
1021 ename
= n_shexp_quote_cp(name
, FAL0
);
1023 if (!strcmp(name
, mailname
)) {
1024 n_err(_("Cannot remove current mailbox %s\n"), ename
);
1029 size_t vl
= strlen(ename
) + fmt_len
+1;
1030 char *vb
= salloc(vl
);
1032 snprintf(vb
, vl
, fmt
, ename
);
1033 asw
= getapproval(vb
, TRU1
);
1038 switch (which_protocol(name
)) {
1040 if (unlink(name
) == -1) { /* TODO do not handle .gz .bz2 .xz.. */
1046 if (!stat(name
, &sb
) && S_ISDIR(sb
.st_mode
)) {
1057 n_err(_("Cannot remove POP3 mailbox %s\n"), ename
);
1061 if (maildir_remove(name
) != OKAY
)
1065 n_err(_("Not removed: unknown protocol: %s\n"), ename
);
1069 } while (*++args
!= NULL
);
1078 char **args
= v
, *old
, *new;
1079 enum protocol oldp
, newp
;
1085 if (args
[0] == NULL
|| args
[1] == NULL
|| args
[2] != NULL
) {
1086 n_err(_("Synopsis: rename: <old> <new>\n"));
1090 if ((old
= expand(args
[0])) == NULL
)
1092 oldp
= which_protocol(old
);
1093 if ((new = expand(args
[1])) == NULL
)
1095 newp
= which_protocol(new);
1097 if (!strcmp(old
, mailname
) || !strcmp(new, mailname
)) {
1098 n_err(_("Cannot rename current mailbox %s\n"),
1099 n_shexp_quote_cp(old
, FAL0
));
1105 if (newp
== PROTO_POP3
)
1109 if (link(old
, new) == -1) {
1124 } else if (unlink(old
) == -1) {
1130 if (rename(old
, new) == -1) {
1137 n_err(_("Cannot rename POP3 mailboxes\n"));
1142 n_err(_("Unknown protocol in %s and %s; not renamed\n"),
1143 n_shexp_quote_cp(old
, FAL0
), n_shexp_quote_cp(new, FAL0
));
1153 c_urlencode(void *v
) /* XXX IDNA?? */
1158 OBSOLETE("`urlencode': please use `urlcodec enc[ode]' instead");
1160 for (ap
= v
; *ap
!= NULL
; ++ap
) {
1161 char *in
= *ap
, *out
= urlxenc(in
, FAL0
);
1164 out
= n_UNCONST(V_(n_error
));
1165 printf(" in: <%s> (%" PRIuZ
" bytes)\nout: <%s> (%" PRIuZ
" bytes)\n",
1166 in
, strlen(in
), out
, strlen(out
));
1173 c_urldecode(void *v
) /* XXX IDNA?? */
1178 OBSOLETE("`urldecode': please use `urlcodec dec[ode]' instead");
1180 for (ap
= v
; *ap
!= NULL
; ++ap
) {
1181 char *in
= *ap
, *out
= urlxdec(in
);
1184 out
= n_UNCONST(V_(n_error
));
1185 printf(" in: <%s> (%" PRIuZ
" bytes)\nout: <%s> (%" PRIuZ
" bytes)\n",
1186 in
, strlen(in
), out
, strlen(out
));