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
47 #define POP3_ANSWER(RV,ACTIONSTOP) \
48 do if (((RV) = pop3_answer(mp)) == STOP) {\
52 #define POP3_OUT(RV,X,Y,ACTIONSTOP) \
54 if (((RV) = pop3_finish(mp)) == STOP) {\
57 if (options & OPT_VERBOSE)\
58 fprintf(stderr, ">>> %s", X);\
60 if (((RV) = swrite(&mp->mb_sock, X)) == STOP) {\
65 static char *_pop3_buf
;
66 static size_t _pop3_bufsize
;
67 static sigjmp_buf _pop3_jmp
;
68 static sighandler_type _pop3_savealrm
;
69 static int _pop3_keepalive
;
70 static int volatile _pop3_lock
;
72 /* Perform entire login handshake */
73 static enum okay
_pop3_login(struct mailbox
*mp
, char *xuser
, char *pass
,
74 char const *uhp
, char const *xserver
);
76 /* APOP: get greeting credential or NULL */
78 static char * _pop3_lookup_apop_timestamp(char const *bp
);
81 static bool_t
_pop3_use_starttls(char const *uhp
);
83 /* APOP: shall we use it (for uhp)? */
84 static bool_t
_pop3_no_apop(char const *uhp
);
86 /* Several authentication methods */
88 static enum okay
_pop3_auth_apop(struct mailbox
*mp
, char *xuser
, char *pass
,
91 static enum okay
_pop3_auth_plain(struct mailbox
*mp
, char *xuser
, char *pass
);
93 static void pop3_timer_off(void);
94 static enum okay
pop3_answer(struct mailbox
*mp
);
95 static enum okay
pop3_finish(struct mailbox
*mp
);
96 static void pop3catch(int s
);
97 static void _pop3_maincatch(int s
);
98 static enum okay
pop3_noop1(struct mailbox
*mp
);
99 static void pop3alarm(int s
);
100 static enum okay
pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
);
101 static enum okay
pop3_list(struct mailbox
*mp
, int n
, size_t *size
);
102 static void pop3_init(struct mailbox
*mp
, int n
);
103 static void pop3_dates(struct mailbox
*mp
);
104 static void pop3_setptr(struct mailbox
*mp
);
105 static enum okay
pop3_get(struct mailbox
*mp
, struct message
*m
,
107 static enum okay
pop3_exit(struct mailbox
*mp
);
108 static enum okay
pop3_delete(struct mailbox
*mp
, int n
);
109 static enum okay
pop3_update(struct mailbox
*mp
);
112 _pop3_login(struct mailbox
*mp
, char *xuser
, char *pass
, char const *uhp
,
122 /* Get the greeting, check wether APOP is advertised */
123 POP3_ANSWER(rv
, goto jleave
);
125 ts
= _pop3_lookup_apop_timestamp(_pop3_buf
);
128 if ((cp
= strchr(xserver
, ':')) != NULL
) { /* TODO GENERIC URI PARSE! */
129 size_t l
= (size_t)(cp
- xserver
);
130 char *x
= salloc(l
+ 1);
131 memcpy(x
, xserver
, l
);
136 /* If not yet secured, can we upgrade to TLS? */
138 if (mp
->mb_sock
.s_use_ssl
== 0 && _pop3_use_starttls(uhp
)) {
139 POP3_OUT(rv
, "STLS\r\n", MB_COMD
, goto jleave
);
140 POP3_ANSWER(rv
, goto jleave
);
141 if ((rv
= ssl_open(xserver
, &mp
->mb_sock
, uhp
)) != OKAY
)
145 if (_pop3_use_starttls(uhp
)) {
146 fprintf(stderr
, "No SSL support compiled in.\n");
152 /* Use the APOP single roundtrip? */
153 if (!_pop3_no_apop(uhp
)) {
156 if ((rv
= _pop3_auth_apop(mp
, xuser
, pass
, ts
)) != OKAY
)
157 fprintf(stderr
, tr(276,
158 "POP3 `APOP' authentication failed, "
159 "maybe try setting *pop3-no-apop*\n"));
163 if (options
& OPT_VERBOSE
)
164 fprintf(stderr
, tr(204, "No POP3 `APOP' support "
165 "available, sending password in clear text\n"));
167 rv
= _pop3_auth_plain(mp
, xuser
, pass
);
175 _pop3_lookup_apop_timestamp(char const *bp
)
178 * A POP3 server which implements the APOP command will include
179 * a timestamp in its banner greeting. The syntax of the timestamp
180 * corresponds to the `msg-id' in [RFC822]
182 * msg-id = "<" addr-spec ">"
183 * addr-spec = local-part "@" domain */
190 if ((cp
= strchr(bp
, '<')) == NULL
)
193 /* xxx What about malformed APOP timestamp (<@>) here? */
194 for (ep
= cp
; *ep
; ep
++) {
199 else if (*ep
== '>') {
208 tl
= PTR2SIZE(++ep
- cp
);
219 _pop3_use_starttls(char const *uhp
)
224 if (!(rv
= ok_blook(pop3_use_starttls
)))
225 rv
= vok_blook(savecat("pop3-use-starttls-", uhp
));
231 _pop3_no_apop(char const *uhp
)
236 if (!(rv
= ok_blook(pop3_no_apop
)))
237 rv
= vok_blook(savecat("pop3-no-apop-", uhp
));
244 _pop3_auth_apop(struct mailbox
*mp
, char *xuser
, char *pass
, char const *ts
)
246 unsigned char digest
[16];
247 char hex
[MD5TOHEX_SIZE
];
254 for (tl
= strlen(ts
);;) {
256 if (!getcredentials(&user
, &pass
))
260 md5_update(&ctx
, (unsigned char*)UNCONST(ts
), tl
);
261 md5_update(&ctx
, (unsigned char*)pass
, strlen(pass
));
262 md5_final(digest
, &ctx
);
263 md5tohex(hex
, digest
);
266 cp
= ac_alloc(5 + i
+ 1 + MD5TOHEX_SIZE
+ 2 +1);
268 memcpy(cp
, "APOP ", 5);
269 memcpy(cp
+ 5, user
, i
);
272 memcpy(cp
+ i
, hex
, MD5TOHEX_SIZE
);
274 memcpy(cp
+ i
, "\r\n\0", 3);
275 POP3_OUT(rv
, cp
, MB_COMD
, goto jcont
);
276 POP3_ANSWER(rv
, goto jcont
);
287 #endif /* HAVE_MD5 */
290 _pop3_auth_plain(struct mailbox
*mp
, char *xuser
, char *pass
)
297 /* The USER/PASS plain text version */
300 if (!getcredentials(&user
, &pass
))
305 cp
= ac_alloc(MAX(ul
, pl
) + 5 + 2 +1);
307 memcpy(cp
, "USER ", 5);
308 memcpy(cp
+ 5, user
, ul
);
309 memcpy(cp
+ 5 + ul
, "\r\n\0", 3);
310 POP3_OUT(rv
, cp
, MB_COMD
, goto jcont
);
311 POP3_ANSWER(rv
, goto jcont
);
313 memcpy(cp
, "PASS ", 5);
314 memcpy(cp
+ 5, pass
, pl
);
315 memcpy(cp
+ 5 + pl
, "\r\n\0", 3);
316 POP3_OUT(rv
, cp
, MB_COMD
, goto jcont
);
317 POP3_ANSWER(rv
, goto jcont
);
333 if (_pop3_keepalive
> 0) {
335 safe_signal(SIGALRM
, _pop3_savealrm
);
341 pop3_answer(struct mailbox
*mp
)
348 if ((sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, NULL
, &mp
->mb_sock
)) > 0) {
349 if ((mp
->mb_active
& (MB_COMD
| MB_MULT
)) == MB_MULT
)
351 if (options
& OPT_VERBOSE
)
352 fputs(_pop3_buf
, stderr
);
353 switch (*_pop3_buf
) {
356 mp
->mb_active
&= ~MB_COMD
;
360 mp
->mb_active
= MB_NONE
;
361 fprintf(stderr
, tr(218, "POP3 error: %s"), _pop3_buf
);
364 /* If the answer starts neither with '+' nor with
365 * '-', it must be part of a multiline response,
366 * e. g. because the user interrupted a file
367 * download. Get lines until a single dot appears */
369 while (_pop3_buf
[0] != '.' || _pop3_buf
[1] != '\r' ||
370 _pop3_buf
[2] != '\n' || _pop3_buf
[3] != '\0') {
371 sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, NULL
, &mp
->mb_sock
);
375 mp
->mb_active
&= ~MB_MULT
;
376 if (mp
->mb_active
!= MB_NONE
)
382 mp
->mb_active
= MB_NONE
;
389 pop3_finish(struct mailbox
*mp
)
392 while (mp
->mb_sock
.s_fd
> 0 && mp
->mb_active
!= MB_NONE
)
401 NYD_X
; /* Signal handler */
402 termios_state_reset();
405 fprintf(stderr
, tr(102, "Interrupt\n"));
406 siglongjmp(_pop3_jmp
, 1);
409 fprintf(stderr
, "Received SIGPIPE during POP3 operation\n");
415 _pop3_maincatch(int s
)
417 NYD_X
; /* Signal handler */
420 if (interrupts
++ == 0)
421 fprintf(stderr
, tr(102, "Interrupt\n"));
427 pop3_noop1(struct mailbox
*mp
)
432 POP3_OUT(rv
, "NOOP\r\n", MB_COMD
, goto jleave
);
433 POP3_ANSWER(rv
, goto jleave
);
442 sighandler_type
volatile saveint
, savepipe
;
443 NYD_X
; /* Signal handler */
446 if (_pop3_lock
++ == 0) {
447 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
448 safe_signal(SIGINT
, &_pop3_maincatch
);
449 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
450 if (sigsetjmp(_pop3_jmp
, 1)) {
451 safe_signal(SIGINT
, saveint
);
452 safe_signal(SIGPIPE
, savepipe
);
455 if (savepipe
!= SIG_IGN
)
456 safe_signal(SIGPIPE
, pop3catch
);
457 if (pop3_noop1(&mb
) != OKAY
) {
458 safe_signal(SIGINT
, saveint
);
459 safe_signal(SIGPIPE
, savepipe
);
462 safe_signal(SIGINT
, saveint
);
463 safe_signal(SIGPIPE
, savepipe
);
466 alarm(_pop3_keepalive
);
472 pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
)
478 POP3_OUT(rv
, "STAT\r\n", MB_COMD
, goto jleave
);
479 POP3_ANSWER(rv
, goto jleave
);
481 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
483 while (*cp
!= '\0' && spacechar(*cp
))
487 *cnt
= (int)strtol(cp
, NULL
, 10);
488 while (*cp
!= '\0' && !spacechar(*cp
))
490 while (*cp
!= '\0' && spacechar(*cp
))
493 *size
= (int)strtol(cp
, NULL
, 10);
500 fprintf(stderr
, tr(260, "invalid POP3 STAT response: %s\n"),
508 pop3_list(struct mailbox
*mp
, int n
, size_t *size
)
510 char o
[LINESIZE
], *cp
;
514 snprintf(o
, sizeof o
, "LIST %u\r\n", n
);
515 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
516 POP3_ANSWER(rv
, goto jleave
);
518 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
520 while (*cp
!= '\0' && spacechar(*cp
))
522 while (*cp
!= '\0' && !spacechar(*cp
))
524 while (*cp
!= '\0' && spacechar(*cp
))
527 *size
= (size_t)strtol(cp
, NULL
, 10);
536 pop3_init(struct mailbox
*mp
, int n
)
543 m
->m_flag
= MUSED
| MNEW
| MNOFROM
| MNEWEST
;
546 pop3_list(mp
, PTR2SIZE(m
- message
+ 1), &m
->m_xsize
);
548 if ((cp
= hfield1("status", m
)) != NULL
) {
549 while (*cp
!= '\0') {
561 pop3_dates(struct mailbox
*mp
)
567 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
568 substdate(message
+ i
);
573 pop3_setptr(struct mailbox
*mp
)
578 message
= scalloc(msgCount
+ 1, sizeof *message
);
579 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
583 message
[msgCount
].m_size
= 0;
584 message
[msgCount
].m_lines
= 0;
590 pop3_get(struct mailbox
*mp
, struct message
*m
, enum needspec
volatile need
)
592 char o
[LINESIZE
], *line
, *lp
;
593 sighandler_type
volatile saveint
, savepipe
;
594 size_t linesize
, linelen
, size
;
595 int number
, emptyline
, lines
;
601 saveint
= savepipe
= SIG_IGN
;
603 number
= (int)PTR2SIZE(m
- message
+ 1);
607 if (mp
->mb_sock
.s_fd
< 0) {
608 fprintf(stderr
, tr(219, "POP3 connection already closed.\n"));
613 if (_pop3_lock
++ == 0) {
614 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
615 safe_signal(SIGINT
, &_pop3_maincatch
);
616 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
617 if (sigsetjmp(_pop3_jmp
, 1)) {
618 safe_signal(SIGINT
, saveint
);
619 safe_signal(SIGPIPE
, savepipe
);
623 if (savepipe
!= SIG_IGN
)
624 safe_signal(SIGPIPE
, pop3catch
);
627 fseek(mp
->mb_otf
, 0L, SEEK_END
);
628 offset
= ftell(mp
->mb_otf
);
632 snprintf(o
, sizeof o
, "TOP %u 0\r\n", number
);
635 snprintf(o
, sizeof o
, "RETR %u\r\n", number
);
640 POP3_OUT(rv
, o
, MB_COMD
| MB_MULT
, goto jleave
);
642 if (pop3_answer(mp
) == STOP
) {
643 if (need
== NEED_HEADER
) {
644 /* The TOP POP3 command is optional, so retry with entire message */
653 while (sgetline(&line
, &linesize
, &linelen
, &mp
->mb_sock
) > 0) {
654 if (line
[0] == '.' && line
[1] == '\r' && line
[2] == '\n' &&
656 mp
->mb_active
&= ~MB_MULT
;
659 if (line
[0] == '.') {
665 * Need to mask 'From ' lines. This cannot be done properly
666 * since some servers pass them as 'From ' and others as
667 * '>From '. Although one could identify the first kind of
668 * server in principle, it is not possible to identify the
669 * second as '>From ' may also come from a server of the
670 * first type as actual data. So do what is absolutely
671 * necessary only - mask 'From '.
673 * If the line is the first line of the message header, it
674 * is likely a real 'From ' line. In this case, it is just
675 * ignored since it violates all standards.
676 * TODO i have *never* seen the latter?!?!?
679 /* Since we simply copy over data without doing any transfer
680 * encoding reclassification/adjustment we *have* to perform
681 * RFC 4155 compliant From_ quoting here */
682 if (is_head(lp
, linelen
)) {
685 fputc('>', mp
->mb_otf
);
689 if (lp
[linelen
-1] == '\n' && (linelen
== 1 ||
690 lp
[linelen
-2] == '\r')) {
691 emptyline
= linelen
<= 2;
693 fwrite(lp
, 1, linelen
- 2, mp
->mb_otf
);
694 fputc('\n', mp
->mb_otf
);
698 fwrite(lp
, 1, linelen
, mp
->mb_otf
);
703 /* This is very ugly; but some POP3 daemons don't end a
704 * message with \r\n\r\n, and we need \n\n for mbox format */
705 fputc('\n', mp
->mb_otf
);
711 m
->m_block
= mailx_blockof(offset
);
712 m
->m_offset
= mailx_offsetof(offset
);
717 m
->m_have
|= HAVE_HEADER
;
720 m
->m_have
|= HAVE_HEADER
| HAVE_BODY
;
721 m
->m_xlines
= m
->m_lines
;
722 m
->m_xsize
= m
->m_size
;
732 if (saveint
!= SIG_IGN
)
733 safe_signal(SIGINT
, saveint
);
734 if (savepipe
!= SIG_IGN
)
735 safe_signal(SIGPIPE
, savepipe
);
744 pop3_exit(struct mailbox
*mp
)
749 POP3_OUT(rv
, "QUIT\r\n", MB_COMD
, goto jleave
);
750 POP3_ANSWER(rv
, goto jleave
);
757 pop3_delete(struct mailbox
*mp
, int n
)
763 snprintf(o
, sizeof o
, "DELE %u\r\n", n
);
764 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
765 POP3_ANSWER(rv
, goto jleave
);
772 pop3_update(struct mailbox
*mp
)
775 int dodel
, c
, gotcha
, held
;
781 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
)
782 if (m
->m_flag
& MBOX
)
789 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
) {
791 dodel
= m
->m_flag
& MDELETED
;
793 dodel
= !((m
->m_flag
& MPRESERVE
) || !(m
->m_flag
& MTOUCH
));
795 pop3_delete(mp
, PTR2SIZE(m
- message
+ 1));
800 if (gotcha
&& edit
) {
801 printf(tr(168, "\"%s\" "), displayname
);
802 printf((ok_blook(bsdcompat
) || ok_blook(bsdmsgs
))
803 ? tr(170, "complete\n") : tr(212, "updated.\n"));
804 } else if (held
&& !edit
) {
806 printf(tr(155, "Held 1 message in %s\n"), displayname
);
808 printf(tr(156, "Held %d messages in %s\n"), held
, displayname
);
818 sighandler_type
volatile saveint
, savepipe
;
823 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
824 safe_signal(SIGINT
, &_pop3_maincatch
);
825 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
826 if (sigsetjmp(_pop3_jmp
, 1) == 0) {
827 if (savepipe
!= SIG_IGN
)
828 safe_signal(SIGPIPE
, pop3catch
);
829 rv
= pop3_noop1(&mb
);
831 safe_signal(SIGINT
, saveint
);
832 safe_signal(SIGPIPE
, savepipe
);
839 pop3_setfile(char const *server
, int nmail
, int isedit
)
842 sighandler_type saveint
, savepipe
;
843 char * volatile user
, * volatile pass
;
844 char const *cp
, *uhp
, * volatile sp
= server
;
845 int use_ssl
= 0, rv
= 1;
851 if (!strncmp(sp
, "pop3://", 7)) {
855 } else if (!strncmp(sp
, "pop3s://", 8)) {
861 pass
= lookup_password_for_token(uhp
);
863 if ((cp
= last_at_before_slash(sp
)) != NULL
) {
864 user
= salloc(cp
- sp
+1);
865 memcpy(user
, sp
, cp
- sp
);
866 user
[cp
- sp
] = '\0';
868 user
= urlxdec(user
);
872 if (sopen(sp
, &so
, use_ssl
, uhp
, (use_ssl
? "pop3s" : "pop3")) != OKAY
) {
877 edit
= (isedit
!= 0);
878 if (mb
.mb_sock
.s_fd
>= 0)
889 mb
.mb_type
= MB_VOID
;
893 saveint
= safe_signal(SIGINT
, SIG_IGN
);
894 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
895 if (sigsetjmp(_pop3_jmp
, 1)) {
897 safe_signal(SIGINT
, saveint
);
898 safe_signal(SIGPIPE
, savepipe
);
902 if (saveint
!= SIG_IGN
)
903 safe_signal(SIGINT
, pop3catch
);
904 if (savepipe
!= SIG_IGN
)
905 safe_signal(SIGPIPE
, pop3catch
);
907 if ((cp
= ok_vlook(pop3_keepalive
)) != NULL
) {
908 if ((_pop3_keepalive
= (int)strtol(cp
, NULL
, 10)) > 0) {
909 _pop3_savealrm
= safe_signal(SIGALRM
, pop3alarm
);
910 alarm(_pop3_keepalive
);
914 mb
.mb_sock
.s_desc
= "POP3";
915 mb
.mb_sock
.s_onclose
= pop3_timer_off
;
916 if (_pop3_login(&mb
, user
, pass
, uhp
, sp
) != OKAY
||
917 pop3_stat(&mb
, &mailsize
, &msgCount
) != OKAY
) {
920 safe_signal(SIGINT
, saveint
);
921 safe_signal(SIGPIPE
, savepipe
);
925 mb
.mb_type
= MB_POP3
;
926 mb
.mb_perm
= (options
& OPT_R_FLAG
) ? 0 : MB_DELE
;
931 safe_signal(SIGINT
, saveint
);
932 safe_signal(SIGPIPE
, savepipe
);
934 if (!edit
&& msgCount
== 0) {
935 if (mb
.mb_type
== MB_POP3
&& !ok_blook(emptystart
))
936 fprintf(stderr
, tr(258, "No mail at %s\n"), server
);
946 pop3_header(struct message
*m
)
951 rv
= pop3_get(&mb
, m
, (ok_blook(pop3_bulk_load
) ? NEED_BODY
: NEED_HEADER
));
957 pop3_body(struct message
*m
)
962 rv
= pop3_get(&mb
, m
, NEED_BODY
);
970 sighandler_type
volatile saveint
, savepipe
;
973 if (mb
.mb_sock
.s_fd
< 0) {
974 fprintf(stderr
, tr(219, "POP3 connection already closed.\n"));
979 saveint
= safe_signal(SIGINT
, SIG_IGN
);
980 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
981 if (sigsetjmp(_pop3_jmp
, 1)) {
982 safe_signal(SIGINT
, saveint
);
983 safe_signal(SIGPIPE
, saveint
);
987 if (saveint
!= SIG_IGN
)
988 safe_signal(SIGINT
, pop3catch
);
989 if (savepipe
!= SIG_IGN
)
990 safe_signal(SIGPIPE
, pop3catch
);
994 safe_signal(SIGINT
, saveint
);
995 safe_signal(SIGPIPE
, savepipe
);
1000 #endif /* HAVE_POP3 */
1002 /* vim:set fenc=utf-8:s-it-mode */