1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ POP3 (RFCs 1939, 2595) client.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2014 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
9 * Gunnar Ritter. 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 Gunnar Ritter
22 * and his contributors.
23 * 4. Neither the name of Gunnar Ritter nor the names of his 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 GUNNAR RITTER 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 GUNNAR RITTER 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
52 #define POP3_ANSWER(RV,ACTIONSTOP) \
53 do if (((RV) = pop3_answer(mp)) == STOP) {\
57 #define POP3_OUT(RV,X,Y,ACTIONSTOP) \
59 if (((RV) = pop3_finish(mp)) == STOP) {\
62 if (options & OPT_VERBVERB)\
63 fprintf(stderr, ">>> %s", X);\
65 if (((RV) = swrite(&mp->mb_sock, X)) == STOP) {\
70 static char *_pop3_buf
;
71 static size_t _pop3_bufsize
;
72 static sigjmp_buf _pop3_jmp
;
73 static sighandler_type _pop3_savealrm
;
74 static int _pop3_keepalive
;
75 static int volatile _pop3_lock
;
77 /* Perform entire login handshake */
78 static enum okay
_pop3_login(struct mailbox
*mp
, struct sockconn
*scp
);
80 /* APOP: get greeting credential or NULL */
82 static char * _pop3_lookup_apop_timestamp(char const *bp
);
85 static bool_t
_pop3_use_starttls(struct sockconn
const *scp
);
87 /* APOP: shall we use it? */
88 static bool_t
_pop3_no_apop(struct sockconn
const *scp
);
90 /* Several authentication methods */
92 static enum okay
_pop3_auth_apop(struct mailbox
*mp
,
93 struct sockconn
const *scp
, char const *ts
);
95 static enum okay
_pop3_auth_plain(struct mailbox
*mp
,
96 struct sockconn
const *scp
);
98 static void pop3_timer_off(void);
99 static enum okay
pop3_answer(struct mailbox
*mp
);
100 static enum okay
pop3_finish(struct mailbox
*mp
);
101 static void pop3catch(int s
);
102 static void _pop3_maincatch(int s
);
103 static enum okay
pop3_noop1(struct mailbox
*mp
);
104 static void pop3alarm(int s
);
105 static enum okay
pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
);
106 static enum okay
pop3_list(struct mailbox
*mp
, int n
, size_t *size
);
107 static void pop3_init(struct mailbox
*mp
, int n
);
108 static void pop3_dates(struct mailbox
*mp
);
109 static void pop3_setptr(struct mailbox
*mp
);
110 static enum okay
pop3_get(struct mailbox
*mp
, struct message
*m
,
112 static enum okay
pop3_exit(struct mailbox
*mp
);
113 static enum okay
pop3_delete(struct mailbox
*mp
, int n
);
114 static enum okay
pop3_update(struct mailbox
*mp
);
117 _pop3_login(struct mailbox
*mp
, struct sockconn
*scp
)
125 /* Get the greeting, check wether APOP is advertised */
126 POP3_ANSWER(rv
, goto jleave
);
128 ts
= _pop3_lookup_apop_timestamp(_pop3_buf
);
131 /* If not yet secured, can we upgrade to TLS? */
133 if (!scp
->sc_url
.url_needs_tls
&& _pop3_use_starttls(scp
)) {
134 POP3_OUT(rv
, "STLS" NL
, MB_COMD
, goto jleave
);
135 POP3_ANSWER(rv
, goto jleave
);
136 if ((rv
= ssl_open(scp
->sc_url
.url_host
.s
, &scp
->sc_sock
,
137 scp
->sc_url
.url_u_h_p
.s
)) != OKAY
)
141 if (_pop3_use_starttls(scp
->sc_url
.url_u_h_p
.s
)) {
142 fprintf(stderr
, "No SSL support compiled in.\n");
148 /* Use the APOP single roundtrip? */
149 if (!_pop3_no_apop(scp
)) {
152 if ((rv
= _pop3_auth_apop(mp
, scp
, ts
)) != OKAY
)
153 fprintf(stderr
, _("POP3 `APOP' authentication failed, "
154 "maybe try setting *pop3-no-apop*\n"));
158 if (options
& OPT_VERB
)
159 fprintf(stderr
, _("No POP3 `APOP' support "
160 "available, sending password in clear text\n"));
163 rv
= _pop3_auth_plain(mp
, scp
);
171 _pop3_lookup_apop_timestamp(char const *bp
)
174 * A POP3 server which implements the APOP command will include
175 * a timestamp in its banner greeting. The syntax of the timestamp
176 * corresponds to the `msg-id' in [RFC822]
178 * msg-id = "<" addr-spec ">"
179 * addr-spec = local-part "@" domain */
186 if ((cp
= strchr(bp
, '<')) == NULL
)
189 /* xxx What about malformed APOP timestamp (<@>) here? */
190 for (ep
= cp
; *ep
!= '\0'; ++ep
) {
195 else if (*ep
== '>') {
204 tl
= PTR2SIZE(++ep
- cp
);
215 _pop3_use_starttls(struct sockconn
const *scp
)
220 if (!(rv
= ok_blook(pop3_use_starttls
)))
221 if (!ok_blook(v15_compat
) ||
222 !(rv
= vok_blook(savecat("pop3-use-starttls-",
223 scp
->sc_url
.url_h_p
.s
))))
224 rv
= vok_blook(savecat("pop3-use-starttls-", scp
->sc_url
.url_u_h_p
.s
));
230 _pop3_no_apop(struct sockconn
const *scp
)
235 if (!(rv
= ok_blook(pop3_no_apop
)))
236 if (!ok_blook(v15_compat
) ||
237 !(rv
= vok_blook(savecat("pop3-no-apop-", scp
->sc_url
.url_h_p
.s
))))
238 rv
= vok_blook(savecat("pop3-no-apop-", scp
->sc_url
.url_u_h_p
.s
));
245 _pop3_auth_apop(struct mailbox
*mp
, struct sockconn
const *scp
, char const *ts
)
247 unsigned char digest
[16];
248 char hex
[MD5TOHEX_SIZE
], *cp
;
255 md5_update(&ctx
, (uc_i
*)UNCONST(ts
), strlen(ts
));
256 md5_update(&ctx
, (uc_i
*)scp
->sc_cred
.cc_pass
.s
, scp
->sc_cred
.cc_pass
.l
);
257 md5_final(digest
, &ctx
);
258 md5tohex(hex
, digest
);
260 i
= scp
->sc_cred
.cc_user
.l
;
261 cp
= ac_alloc(5 + i
+ 1 + MD5TOHEX_SIZE
+ sizeof(NL
)-1 +1);
263 memcpy(cp
, "APOP ", 5);
264 memcpy(cp
+ 5, scp
->sc_cred
.cc_user
.s
, i
);
267 memcpy(cp
+ i
, hex
, MD5TOHEX_SIZE
);
269 memcpy(cp
+ i
, NL
, sizeof(NL
));
270 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
271 POP3_ANSWER(rv
, goto jleave
);
279 #endif /* HAVE_MD5 */
282 _pop3_auth_plain(struct mailbox
*mp
, struct sockconn
const *scp
)
288 /* The USER/PASS plain text version */
289 cp
= ac_alloc(MAX(scp
->sc_cred
.cc_user
.l
, scp
->sc_cred
.cc_pass
.l
) + 5 +
292 memcpy(cp
, "USER ", 5);
293 memcpy(cp
+ 5, scp
->sc_cred
.cc_user
.s
, scp
->sc_cred
.cc_user
.l
);
294 memcpy(cp
+ 5 + scp
->sc_cred
.cc_user
.l
, NL
, sizeof(NL
));
295 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
296 POP3_ANSWER(rv
, goto jleave
);
298 memcpy(cp
, "PASS ", 5);
299 memcpy(cp
+ 5, scp
->sc_cred
.cc_pass
.s
, scp
->sc_cred
.cc_pass
.l
);
300 memcpy(cp
+ 5 + scp
->sc_cred
.cc_pass
.l
, NL
, sizeof(NL
));
301 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
302 POP3_ANSWER(rv
, goto jleave
);
315 if (_pop3_keepalive
> 0) {
317 safe_signal(SIGALRM
, _pop3_savealrm
);
323 pop3_answer(struct mailbox
*mp
)
330 if ((sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, NULL
, &mp
->mb_sock
)) > 0) {
331 if ((mp
->mb_active
& (MB_COMD
| MB_MULT
)) == MB_MULT
)
333 if (options
& OPT_VERBVERB
)
334 fputs(_pop3_buf
, stderr
);
335 switch (*_pop3_buf
) {
338 mp
->mb_active
&= ~MB_COMD
;
342 mp
->mb_active
= MB_NONE
;
343 fprintf(stderr
, _("POP3 error: %s"), _pop3_buf
);
346 /* If the answer starts neither with '+' nor with '-', it must be part
347 * of a multiline response. Get lines until a single dot appears */
349 while (_pop3_buf
[0] != '.' || _pop3_buf
[1] != NL
[0] ||
350 _pop3_buf
[2] != NL
[1] || _pop3_buf
[3] != '\0') {
351 sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, NULL
, &mp
->mb_sock
);
355 mp
->mb_active
&= ~MB_MULT
;
356 if (mp
->mb_active
!= MB_NONE
)
362 mp
->mb_active
= MB_NONE
;
369 pop3_finish(struct mailbox
*mp
)
372 while (mp
->mb_sock
.s_fd
> 0 && mp
->mb_active
!= MB_NONE
)
381 NYD_X
; /* Signal handler */
384 fprintf(stderr
, _("Interrupt\n"));
385 siglongjmp(_pop3_jmp
, 1);
388 fprintf(stderr
, "Received SIGPIPE during POP3 operation\n");
394 _pop3_maincatch(int s
)
396 NYD_X
; /* Signal handler */
399 if (interrupts
++ == 0)
400 fprintf(stderr
, _("Interrupt\n"));
406 pop3_noop1(struct mailbox
*mp
)
411 POP3_OUT(rv
, "NOOP" NL
, MB_COMD
, goto jleave
);
412 POP3_ANSWER(rv
, goto jleave
);
421 sighandler_type
volatile saveint
, savepipe
;
422 NYD_X
; /* Signal handler */
425 if (_pop3_lock
++ == 0) {
426 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
427 safe_signal(SIGINT
, &_pop3_maincatch
);
428 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
429 if (sigsetjmp(_pop3_jmp
, 1)) {
430 safe_signal(SIGINT
, saveint
);
431 safe_signal(SIGPIPE
, savepipe
);
434 if (savepipe
!= SIG_IGN
)
435 safe_signal(SIGPIPE
, pop3catch
);
436 if (pop3_noop1(&mb
) != OKAY
) {
437 safe_signal(SIGINT
, saveint
);
438 safe_signal(SIGPIPE
, savepipe
);
441 safe_signal(SIGINT
, saveint
);
442 safe_signal(SIGPIPE
, savepipe
);
445 alarm(_pop3_keepalive
);
451 pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
)
457 POP3_OUT(rv
, "STAT" NL
, MB_COMD
, goto jleave
);
458 POP3_ANSWER(rv
, goto jleave
);
460 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
462 while (*cp
!= '\0' && spacechar(*cp
))
466 *cnt
= (int)strtol(cp
, NULL
, 10);
467 while (*cp
!= '\0' && !spacechar(*cp
))
469 while (*cp
!= '\0' && spacechar(*cp
))
472 *size
= (int)strtol(cp
, NULL
, 10);
479 fprintf(stderr
, _("invalid POP3 STAT response: %s\n"), _pop3_buf
);
486 pop3_list(struct mailbox
*mp
, int n
, size_t *size
)
488 char o
[LINESIZE
], *cp
;
492 snprintf(o
, sizeof o
, "LIST %u" NL
, n
);
493 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
494 POP3_ANSWER(rv
, goto jleave
);
496 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
498 while (*cp
!= '\0' && spacechar(*cp
))
500 while (*cp
!= '\0' && !spacechar(*cp
))
502 while (*cp
!= '\0' && spacechar(*cp
))
505 *size
= (size_t)strtol(cp
, NULL
, 10);
514 pop3_init(struct mailbox
*mp
, int n
)
521 m
->m_flag
= MUSED
| MNEW
| MNOFROM
| MNEWEST
;
524 pop3_list(mp
, PTR2SIZE(m
- message
+ 1), &m
->m_xsize
);
526 if ((cp
= hfield1("status", m
)) != NULL
) {
527 while (*cp
!= '\0') {
539 pop3_dates(struct mailbox
*mp
)
545 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
546 substdate(message
+ i
);
551 pop3_setptr(struct mailbox
*mp
)
556 message
= scalloc(msgCount
+ 1, sizeof *message
);
557 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
561 message
[msgCount
].m_size
= 0;
562 message
[msgCount
].m_lines
= 0;
568 pop3_get(struct mailbox
*mp
, struct message
*m
, enum needspec
volatile need
)
570 char o
[LINESIZE
], *line
, *lp
;
571 sighandler_type
volatile saveint
, savepipe
;
572 size_t linesize
, linelen
, size
;
574 int volatile emptyline
;
576 enum okay
volatile rv
;
579 line
= NULL
; /* TODO line pool */
580 saveint
= savepipe
= SIG_IGN
;
582 number
= (int)PTR2SIZE(m
- message
+ 1);
586 if (mp
->mb_sock
.s_fd
< 0) {
587 fprintf(stderr
, _("POP3 connection already closed.\n"));
592 if (_pop3_lock
++ == 0) {
593 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
594 safe_signal(SIGINT
, &_pop3_maincatch
);
595 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
596 if (sigsetjmp(_pop3_jmp
, 1)) {
597 safe_signal(SIGINT
, saveint
);
598 safe_signal(SIGPIPE
, savepipe
);
602 if (savepipe
!= SIG_IGN
)
603 safe_signal(SIGPIPE
, pop3catch
);
606 fseek(mp
->mb_otf
, 0L, SEEK_END
);
607 offset
= ftell(mp
->mb_otf
);
611 snprintf(o
, sizeof o
, "TOP %u 0" NL
, number
);
614 snprintf(o
, sizeof o
, "RETR %u" NL
, number
);
619 POP3_OUT(rv
, o
, MB_COMD
| MB_MULT
, goto jleave
);
621 if (pop3_answer(mp
) == STOP
) {
622 if (need
== NEED_HEADER
) {
623 /* The TOP POP3 command is optional, so retry with entire message */
632 while (sgetline(&line
, &linesize
, &linelen
, &mp
->mb_sock
) > 0) {
633 if (line
[0] == '.' && line
[1] == NL
[0] && line
[2] == NL
[1] &&
635 mp
->mb_active
&= ~MB_MULT
;
638 if (line
[0] == '.') {
644 * Need to mask 'From ' lines. This cannot be done properly
645 * since some servers pass them as 'From ' and others as
646 * '>From '. Although one could identify the first kind of
647 * server in principle, it is not possible to identify the
648 * second as '>From ' may also come from a server of the
649 * first type as actual data. So do what is absolutely
650 * necessary only - mask 'From '.
652 * If the line is the first line of the message header, it
653 * is likely a real 'From ' line. In this case, it is just
654 * ignored since it violates all standards.
655 * TODO i have *never* seen the latter?!?!?
658 /* Since we simply copy over data without doing any transfer
659 * encoding reclassification/adjustment we *have* to perform
660 * RFC 4155 compliant From_ quoting here */
661 if (is_head(lp
, linelen
)) {
662 DBG( fprintf(stderr
, "!! POP3 really needs to quote From?\n"); )
665 fputc('>', mp
->mb_otf
);
669 if (lp
[linelen
-1] == NL
[1] && (linelen
== 1 || lp
[linelen
-2] == NL
[0])) {
670 emptyline
= linelen
<= 2;
672 fwrite(lp
, 1, linelen
- 2, mp
->mb_otf
);
673 fputc('\n', mp
->mb_otf
);
677 fwrite(lp
, 1, linelen
, mp
->mb_otf
);
682 /* This is very ugly; but some POP3 daemons don't end a
683 * message with NL NL, and we need \n\n for mbox format */
684 fputc('\n', mp
->mb_otf
);
690 m
->m_block
= mailx_blockof(offset
);
691 m
->m_offset
= mailx_offsetof(offset
);
696 m
->m_have
|= HAVE_HEADER
;
699 m
->m_have
|= HAVE_HEADER
| HAVE_BODY
;
700 m
->m_xlines
= m
->m_lines
;
701 m
->m_xsize
= m
->m_size
;
711 if (saveint
!= SIG_IGN
)
712 safe_signal(SIGINT
, saveint
);
713 if (savepipe
!= SIG_IGN
)
714 safe_signal(SIGPIPE
, savepipe
);
723 pop3_exit(struct mailbox
*mp
)
728 POP3_OUT(rv
, "QUIT" NL
, MB_COMD
, goto jleave
);
729 POP3_ANSWER(rv
, goto jleave
);
736 pop3_delete(struct mailbox
*mp
, int n
)
742 snprintf(o
, sizeof o
, "DELE %u" NL
, n
);
743 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
744 POP3_ANSWER(rv
, goto jleave
);
751 pop3_update(struct mailbox
*mp
)
754 int dodel
, c
, gotcha
, held
;
760 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
)
761 if (m
->m_flag
& MBOX
)
768 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
) {
770 dodel
= m
->m_flag
& MDELETED
;
772 dodel
= !((m
->m_flag
& MPRESERVE
) || !(m
->m_flag
& MTOUCH
));
774 pop3_delete(mp
, PTR2SIZE(m
- message
+ 1));
779 if (gotcha
&& edit
) {
780 printf(_("\"%s\" "), displayname
);
781 printf((ok_blook(bsdcompat
) || ok_blook(bsdmsgs
))
782 ? _("complete\n") : _("updated.\n"));
783 } else if (held
&& !edit
) {
785 printf(_("Held 1 message in %s\n"), displayname
);
787 printf(_("Held %d messages in %s\n"), held
, displayname
);
797 sighandler_type
volatile saveint
, savepipe
;
802 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
803 safe_signal(SIGINT
, &_pop3_maincatch
);
804 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
805 if (sigsetjmp(_pop3_jmp
, 1) == 0) {
806 if (savepipe
!= SIG_IGN
)
807 safe_signal(SIGPIPE
, pop3catch
);
808 rv
= pop3_noop1(&mb
);
810 safe_signal(SIGINT
, saveint
);
811 safe_signal(SIGPIPE
, savepipe
);
818 pop3_setfile(char const *server
, enum fedit_mode fm
)
821 sighandler_type saveint
, savepipe
;
827 if (fm
& FEDIT_NEWMAIL
)
831 if (!url_parse(&sc
.sc_url
, CPROTO_POP3
, server
))
833 if (!ok_blook(v15_compat
) &&
834 (!sc
.sc_url
.url_had_user
|| sc
.sc_url
.url_pass
.s
!= NULL
)) {
835 fprintf(stderr
, "New-style URL used without *v15-compat* being set\n");
839 if (!(ok_blook(v15_compat
) ? ccred_lookup(&sc
.sc_cred
, &sc
.sc_url
)
840 : ccred_lookup_old(&sc
.sc_cred
, CPROTO_POP3
,
841 (sc
.sc_url
.url_had_user
? sc
.sc_url
.url_eu_h_p
.s
842 : sc
.sc_url
.url_u_h_p
.s
))))
845 if (!sopen(&sc
.sc_sock
, &sc
.sc_url
))
851 edit
= !(fm
& FEDIT_SYSBOX
);
852 if (mb
.mb_sock
.s_fd
>= 0)
863 initbox(sc
.sc_url
.url_p_u_h_p
);
864 mb
.mb_type
= MB_VOID
;
866 mb
.mb_sock
= sc
.sc_sock
;
868 saveint
= safe_signal(SIGINT
, SIG_IGN
);
869 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
870 if (sigsetjmp(_pop3_jmp
, 1)) {
872 safe_signal(SIGINT
, saveint
);
873 safe_signal(SIGPIPE
, savepipe
);
877 if (saveint
!= SIG_IGN
)
878 safe_signal(SIGINT
, pop3catch
);
879 if (savepipe
!= SIG_IGN
)
880 safe_signal(SIGPIPE
, pop3catch
);
882 if ((cp
= ok_vlook(pop3_keepalive
)) != NULL
) {
883 if ((_pop3_keepalive
= (int)strtol(cp
, NULL
, 10)) > 0) {
884 _pop3_savealrm
= safe_signal(SIGALRM
, pop3alarm
);
885 alarm(_pop3_keepalive
);
889 mb
.mb_sock
.s_desc
= sc
.sc_url
.url_proto
;
890 mb
.mb_sock
.s_onclose
= pop3_timer_off
;
891 if (_pop3_login(&mb
, &sc
) != OKAY
||
892 pop3_stat(&mb
, &mailsize
, &msgCount
) != OKAY
) {
895 safe_signal(SIGINT
, saveint
);
896 safe_signal(SIGPIPE
, savepipe
);
900 mb
.mb_type
= MB_POP3
;
901 mb
.mb_perm
= ((options
& OPT_R_FLAG
) || (fm
& FEDIT_RDONLY
)) ? 0 : MB_DELE
;
906 safe_signal(SIGINT
, saveint
);
907 safe_signal(SIGPIPE
, savepipe
);
909 if (!edit
&& msgCount
== 0) {
910 if (mb
.mb_type
== MB_POP3
&& !ok_blook(emptystart
))
911 fprintf(stderr
, _("No mail at %s\n"), server
);
922 pop3_header(struct message
*m
)
927 rv
= pop3_get(&mb
, m
, (ok_blook(pop3_bulk_load
) ? NEED_BODY
: NEED_HEADER
));
933 pop3_body(struct message
*m
)
938 rv
= pop3_get(&mb
, m
, NEED_BODY
);
946 sighandler_type
volatile saveint
, savepipe
;
949 if (mb
.mb_sock
.s_fd
< 0) {
950 fprintf(stderr
, _("POP3 connection already closed.\n"));
955 saveint
= safe_signal(SIGINT
, SIG_IGN
);
956 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
957 if (sigsetjmp(_pop3_jmp
, 1)) {
958 safe_signal(SIGINT
, saveint
);
959 safe_signal(SIGPIPE
, saveint
);
963 if (saveint
!= SIG_IGN
)
964 safe_signal(SIGINT
, pop3catch
);
965 if (savepipe
!= SIG_IGN
)
966 safe_signal(SIGPIPE
, pop3catch
);
970 safe_signal(SIGINT
, saveint
);
971 safe_signal(SIGPIPE
, savepipe
);
979 #endif /* HAVE_POP3 */