2 * S-nail - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 Steffen "Daode" Nurpmeso.
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
46 #endif /* HAVE_WORDEXP */
52 #elif defined (USE_OPENSSL)
53 #include <openssl/ssl.h>
54 #include <openssl/err.h>
55 #include <openssl/x509v3.h>
56 #include <openssl/x509.h>
57 #include <openssl/rand.h>
60 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #ifdef HAVE_ARPA_INET_H
64 #include <arpa/inet.h>
65 #endif /* HAVE_ARPA_INET_H */
66 #endif /* HAVE_SOCKETS */
72 * Mail -- a mail program
77 static void makemessage(void);
78 static void append(struct message
*mp
);
79 static char *globname(char const*name
);
80 static size_t length_of_line(const char *line
, size_t linesize
);
81 static char *fgetline_byone(char **line
, size_t *linesize
, size_t *llen
,
82 FILE *fp
, int appendnl
, size_t n
);
83 static enum okay
get_header(struct message
*mp
);
86 * Set up the input pointers while copying the mail file into /tmp.
89 setptr(FILE *ibuf
, off_t offset
)
95 int maybe
, inhead
, thiscnt
;
97 size_t linesize
= 0, filesize
;
102 memset(&this, 0, sizeof this);
103 this.m_flag
= MUSED
|MNEW
|MNEWEST
;
104 filesize
= mailsize
- offset
;
105 offset
= ftell(mb
.mb_otf
);
107 if (fgetline(&linebuf
, &linesize
, &filesize
, &count
, ibuf
, 0)
109 this.m_xsize
= this.m_size
;
110 this.m_xlines
= this.m_lines
;
111 this.m_have
= HAVE_HEADER
|HAVE_BODY
;
120 if (linebuf
[0] == '\0')
123 fwrite(linebuf
, sizeof *linebuf
, count
, mb
.mb_otf
);
124 if (ferror(mb
.mb_otf
)) {
128 if (linebuf
[count
- 1] == '\n')
129 linebuf
[count
- 1] = '\0';
130 if (maybe
&& linebuf
[0] == 'F' && is_head(linebuf
, count
)) {
131 this.m_xsize
= this.m_size
;
132 this.m_xlines
= this.m_lines
;
133 this.m_have
= HAVE_HEADER
|HAVE_BODY
;
137 this.m_flag
= MUSED
|MNEW
|MNEWEST
;
140 this.m_block
= mailx_blockof(offset
);
141 this.m_offset
= mailx_offsetof(offset
);
143 } else if (linebuf
[0] == 0) {
146 for (cp
= linebuf
, cp2
= "status";; cp
++) {
147 if ((c
= *cp2
++) == 0) {
148 while (c
= *cp
++, whitechar(c
));
151 while ((c
= *cp
++) != '\0')
153 this.m_flag
|= MREAD
;
155 this.m_flag
&= ~MNEW
;
158 if (*cp
!= c
&& *cp
!= upperconv(c
))
161 for (cp
= linebuf
, cp2
= "x-status";; cp
++) {
162 if ((c
= *cp2
++) == 0) {
163 while (c
= *cp
++, whitechar(c
));
166 while ((c
= *cp
++) != '\0')
168 this.m_flag
|= MFLAGGED
;
170 this.m_flag
|=MANSWERED
;
172 this.m_flag
|=MDRAFTED
;
175 if (*cp
!= c
&& *cp
!= upperconv(c
))
180 this.m_size
+= count
;
182 maybe
= linebuf
[0] == 0;
188 * Drop the passed line onto the passed output buffer.
189 * If a write error occurs, return -1, else the count of
190 * characters written, including the newline.
193 putline(FILE *obuf
, char *linebuf
, size_t count
)
195 fwrite(linebuf
, sizeof *linebuf
, count
, obuf
);
203 * Read up a line from the specified input into the line
204 * buffer. Return the number of characters read. Do not
205 * include the newline at the end.
207 * n is the number of characters already read.
210 readline_restart(FILE *ibuf
, char **linebuf
, size_t *linesize
, size_t n
)
216 * Interrupts will cause trouble if we are inside a stdio call. As
217 * this is only relevant if input comes from a terminal, we can simply
218 * bypass it by read() then.
220 if (fileno(ibuf
) == 0 && is_a_tty
[0]) {
221 if (*linebuf
== NULL
|| *linesize
< LINESIZE
+ n
+ 1)
222 *linebuf
= srealloc(*linebuf
,
223 *linesize
= LINESIZE
+ n
+ 1);
225 if (n
>= *linesize
- 128)
226 *linebuf
= srealloc(*linebuf
, *linesize
+= 256);
228 sz
= read(0, *linebuf
+ n
, *linesize
- n
- 1);
231 (*linebuf
)[n
] = '\0';
232 if (n
> 0 && (*linebuf
)[n
- 1] == '\n')
235 if (sz
< 0 && errno
== EINTR
)
238 if ((*linebuf
)[n
- 1] != '\n') {
239 (*linebuf
)[n
++] = '\n';
240 (*linebuf
)[n
] = '\0';
249 * Not reading from standard input or standard input not
250 * a terminal. We read one char at a time as it is the
251 * only way to get lines with embedded NUL characters in
254 if (fgetline_byone(linebuf
, linesize
, &n
, ibuf
, 1, n
) == NULL
)
257 if (n
> 0 && (*linebuf
)[n
- 1] == '\n')
258 (*linebuf
)[--n
] = '\0';
263 * Return a file buffer all ready to read up the
264 * passed message pointer.
267 setinput(struct mailbox
*mp
, struct message
*m
, enum needspec need
)
273 if (m
->m_have
& HAVE_HEADER
)
279 if (m
->m_have
& HAVE_BODY
)
291 if (fseek(mp
->mb_itf
, (long)mailx_positionof(m
->m_block
,
292 m
->m_offset
), SEEK_SET
) < 0) {
294 panic(catgets(catd
, CATSET
, 77, "temporary file seek"));
300 setdot(struct message
*mp
)
312 * Take the data out of the passed ghost file and toss it into
313 * a dynamically allocated message structure.
321 message
[msgCount
].m_size
= 0;
322 message
[msgCount
].m_lines
= 0;
326 * Append the passed message descriptor onto the message structure.
329 append(struct message
*mp
)
331 if (msgCount
+ 1 >= msgspace
)
332 message
= srealloc(message
, (msgspace
+= 64) * sizeof *message
);
334 message
[msgCount
- 1] = *mp
;
338 * Delete a file, but only if the file is a plain file.
345 if (stat(name
, &sb
) < 0)
347 if (!S_ISREG(sb
.st_mode
)) {
351 return(unlink(name
));
354 static int sigdepth
; /* depth of holdsigs() */
355 static sigset_t nset
, oset
;
357 * Hold signals SIGHUP, SIGINT, and SIGQUIT.
363 if (sigdepth
++ == 0) {
365 sigaddset(&nset
, SIGHUP
);
366 sigaddset(&nset
, SIGINT
);
367 sigaddset(&nset
, SIGQUIT
);
368 sigprocmask(SIG_BLOCK
, &nset
, &oset
);
373 * Release signals SIGHUP, SIGINT, and SIGQUIT.
380 sigprocmask(SIG_SETMASK
, &oset
, (sigset_t
*)NULL
);
384 * Determine the size of the file possessed by
392 if (fstat(fileno(iob
), &sbuf
) < 0)
398 * Evaluate a string and expand file meta characters:
399 * +file file in folder directory
400 * any shell meta character
401 * Return the file name as a dynamic string.
404 file_expand(char const*name
)
406 char foldbuf
[PATHSIZE
];
409 char const*orig
= name
;
411 if ((sh
= get_shortcut(name
)) != NULL
)
416 if (name
[0] == '+' && getfold(foldbuf
, sizeof foldbuf
) >= 0) {
417 switch (which_protocol(foldbuf
)) {
418 /* XXX file_expand(): really "ok!" PROTO_MAILDIR misuse? */
421 (void)str_concat_csvl(&s
, foldbuf
, "/", name
+ 1, NULL
);
422 if (s
.l
>= PATHSIZE
) {
423 fprintf(stderr
, tr(83,
424 "\"%s\": Expansion buffer overflow.\n"),
431 fprintf(stderr
, tr(280, "\"%s\": only a local file or "
432 "directory may be used\n"), orig
);
437 /* Catch the most common shell meta character */
438 if (name
[0] == '~' && (name
[1] == '/' || name
[1] == '\0')) {
439 (void)str_concat_csvl(&s
, homedir
, name
+ 1, NULL
);
440 if (s
.l
>= PATHSIZE
) {
441 fprintf(stderr
, tr(83,
442 "\"%s\": Expansion buffer overflow.\n"),
449 if (name
[0] != '|' && anyof(name
, "|&;<>~{}()[]*?$`'\"\\") &&
450 which_protocol(name
) == PROTO_FILE
)
451 return (globname(name
));
452 return (s
.s
? s
.s
: savestr(name
));
456 * Evaluate the string given as a new mailbox name.
457 * Supported meta characters:
458 * % for my system mail box
459 * %user for user's system mail box
460 * # for previous file
461 * & invoker's mbox file
462 * +file file in folder directory
463 * any shell meta character
464 * Return the file name as a dynamic string.
469 char xname
[PATHSIZE
];
470 char foldbuf
[PATHSIZE
];
474 * The order of evaluation is "%" and "#" expand into constants.
475 * "&" can expand into "+". "+" can expand into shell meta characters.
476 * Shell meta characters expand into constants.
477 * This way, we make no recursive expansion.
479 if ((sh
= get_shortcut(name
)) != NULL
)
484 if (name
[1] == ':' && name
[2]) {
488 findmail(name
[1] ? name
+ 1 : myname
, name
[1] != '\0' || uflag
,
489 xname
, sizeof xname
);
490 return savestr(xname
);
494 if (prevfile
[0] == 0) {
495 printf(catgets(catd
, CATSET
, 80, "No previous file\n"));
498 return savestr(prevfile
);
500 if (name
[1] == 0 && (name
= value("MBOX")) == NULL
)
504 if (name
[0] == '@' && which_protocol(mailname
) == PROTO_IMAP
) {
505 snprintf(xname
, sizeof xname
, "%s/%s", protbase(mailname
),
507 name
= savestr(xname
);
509 if (name
[0] == '+' && getfold(foldbuf
, sizeof foldbuf
) >= 0) {
510 snprintf(xname
, sizeof xname
,
511 ((which_protocol(foldbuf
) == PROTO_IMAP
&&
512 strcmp(foldbuf
, protbase(foldbuf
)))
515 name
= savestr(xname
);
516 if (foldbuf
[0] == '%' && foldbuf
[1] == ':')
519 /* catch the most common shell meta character */
520 if (name
[0] == '~' && (name
[1] == '/' || name
[1] == '\0')) {
521 snprintf(xname
, sizeof xname
, "%s%s", homedir
, name
+ 1);
522 name
= savestr(xname
);
524 if (!anyof(name
, "|&;<>~{}()[]*?$`'\"\\"))
526 if (which_protocol(name
) == PROTO_FILE
)
527 return globname(name
);
533 globname(char const*name
)
542 * Some systems (notably Open UNIX 8.0.0) fork a shell for
543 * wordexp() and wait for it; waiting will fail if our SIGCHLD
547 sigaddset(&nset
, SIGCHLD
);
548 sigprocmask(SIG_BLOCK
, &nset
, NULL
);
549 i
= wordexp(name
, &we
, 0);
550 sigprocmask(SIG_UNBLOCK
, &nset
, NULL
);
555 fprintf(stderr
, catgets(catd
, CATSET
, 83,
556 "\"%s\": Expansion buffer overflow.\n"), name
);
561 fprintf(stderr
, catgets(catd
, CATSET
, 242,
562 "Syntax error in \"%s\"\n"), name
);
565 switch (we
.we_wordc
) {
567 cp
= savestr(we
.we_wordv
[0]);
570 fprintf(stderr
, catgets(catd
, CATSET
, 82,
571 "\"%s\": No match.\n"), name
);
575 fprintf(stderr
, catgets(catd
, CATSET
, 84,
576 "\"%s\": Ambiguous.\n"), name
);
581 #else /* !HAVE_WORDEXP */
582 char xname
[PATHSIZE
];
583 char cmdbuf
[PATHSIZE
]; /* also used for file names */
587 extern int wait_status
;
590 if (pipe(pivec
) < 0) {
594 snprintf(cmdbuf
, sizeof cmdbuf
, "echo %s", name
);
595 if ((shell
= value("SHELL")) == NULL
)
597 pid
= start_command(shell
, 0, -1, pivec
[1], "-c", cmdbuf
, NULL
);
605 l
= read(pivec
[0], xname
, sizeof xname
);
614 if (wait_child(pid
) < 0 && WTERMSIG(wait_status
) != SIGPIPE
) {
615 fprintf(stderr
, catgets(catd
, CATSET
, 81,
616 "\"%s\": Expansion failed.\n"), name
);
620 fprintf(stderr
, catgets(catd
, CATSET
, 82,
621 "\"%s\": No match.\n"), name
);
624 if (l
== sizeof xname
) {
625 fprintf(stderr
, catgets(catd
, CATSET
, 83,
626 "\"%s\": Expansion buffer overflow.\n"), name
);
630 for (cp
= &xname
[l
-1]; *cp
== '\n' && cp
> xname
; cp
--)
633 if (strchr(xname
, ' ') && stat(xname
, &sbuf
) < 0) {
634 fprintf(stderr
, catgets(catd
, CATSET
, 84,
635 "\"%s\": Ambiguous.\n"), name
);
638 return savestr(xname
);
639 #endif /* !HAVE_WORDEXP */
643 * Determine the current folder directory name.
646 getfold(char *name
, int size
)
651 if ((folder
= value("folder")) == NULL
)
653 if (*folder
== '/' || ((p
= which_protocol(folder
)) != PROTO_FILE
&&
654 p
!= PROTO_MAILDIR
)) {
655 strncpy(name
, folder
, size
);
658 snprintf(name
, size
, "%s/%s", homedir
, folder
);
664 * Return the name of the dead.letter file.
671 if ((cp
= value("DEAD")) == NULL
|| (cp
= file_expand(cp
)) == NULL
)
672 cp
= file_expand("~/dead.letter");
673 else if (*cp
!= '/') {
674 size_t sz
= strlen(cp
) + 3;
675 char *buf
= ac_alloc(sz
);
677 snprintf(buf
, sz
, "~/%s", cp
);
678 cp
= file_expand(buf
);
685 * line is a buffer with the result of fgets(). Returns the first
686 * newline or the last character read.
689 length_of_line(const char *line
, size_t linesize
)
694 * Last character is always '\0' and was added by fgets.
697 for (i
= 0; i
< linesize
; i
++)
700 return i
< linesize
? i
+ 1 : linesize
;
704 * fgets replacement to handle lines of arbitrary size and with
705 * embedded \0 characters.
706 * line - line buffer. *line be NULL.
707 * linesize - allocated size of line buffer.
708 * count - maximum characters to read. May be NULL.
709 * llen - length_of_line(*line).
711 * appendnl - always terminate line with \n, append if necessary.
714 fgetline(char **line
, size_t *linesize
, size_t *count
, size_t *llen
,
715 FILE *fp
, int appendnl
)
721 * If we have no count, we cannot determine where the
722 * characters returned by fgets() end if there was no
723 * newline. We have to read one character at one.
725 return fgetline_byone(line
, linesize
, llen
, fp
, appendnl
, 0);
726 if (*line
== NULL
|| *linesize
< LINESIZE
)
727 *line
= srealloc(*line
, *linesize
= LINESIZE
);
728 sz
= *linesize
<= *count
? *linesize
: *count
+ 1;
729 if (sz
<= 1 || fgets(*line
, sz
, fp
) == NULL
)
731 * Leave llen untouched; it is used to determine whether
732 * the last line was \n-terminated in some callers.
735 i_llen
= length_of_line(*line
, sz
);
737 while ((*line
)[i_llen
- 1] != '\n') {
738 *line
= srealloc(*line
, *linesize
+= 256);
739 sz
= *linesize
- i_llen
;
740 sz
= (sz
<= *count
? sz
: *count
+ 1);
741 if (sz
<= 1 || fgets(&(*line
)[i_llen
], sz
, fp
) == NULL
) {
743 (*line
)[i_llen
++] = '\n';
744 (*line
)[i_llen
] = '\0';
748 sz
= length_of_line(&(*line
)[i_llen
], sz
);
758 * Read a line, one character at once.
761 fgetline_byone(char **line
, size_t *linesize
, size_t *llen
,
762 FILE *fp
, int appendnl
, size_t n
)
766 if (*line
== NULL
|| *linesize
< LINESIZE
+ n
+ 1)
767 *line
= srealloc(*line
, *linesize
= LINESIZE
+ n
+ 1);
769 if (n
>= *linesize
- 128)
770 *line
= srealloc(*line
, *linesize
+= 256);
794 get_header(struct message
*mp
)
796 switch (mb
.mb_type
) {
801 return pop3_header(mp
);
804 return imap_header(mp
);
813 get_body(struct message
*mp
)
815 switch (mb
.mb_type
) {
820 return pop3_body(mp
);
823 return imap_body(mp
);
832 static long xwrite(int fd
, const char *data
, size_t sz
);
835 xwrite(int fd
, const char *data
, size_t sz
)
841 if ((wo
= write(fd
, data
+ wt
, sz
- wt
)) < 0) {
853 sclose(struct sock
*sp
)
858 if (sp
->s_onclose
!= NULL
)
860 #if defined (USE_NSS)
863 i
= PR_Close(sp
->s_prfd
) == PR_SUCCESS
? 0 : -1;
866 #elif defined (USE_OPENSSL)
869 SSL_shutdown(sp
->s_ssl
);
872 SSL_CTX_free(sp
->s_ctx
);
887 swrite(struct sock
*sp
, const char *data
)
889 return swrite1(sp
, data
, strlen(data
), 0);
893 swrite1(struct sock
*sp
, const char *data
, int sz
, int use_buffer
)
897 if (use_buffer
> 0) {
901 if (sp
->s_wbuf
== NULL
) {
902 sp
->s_wbufsize
= 4096;
903 sp
->s_wbuf
= smalloc(sp
->s_wbufsize
);
906 while (sp
->s_wbufpos
+ sz
> sp
->s_wbufsize
) {
907 di
= sp
->s_wbufsize
- sp
->s_wbufpos
;
909 if (sp
->s_wbufpos
> 0) {
910 memcpy(&sp
->s_wbuf
[sp
->s_wbufpos
], data
, di
);
911 ok
= swrite1(sp
, sp
->s_wbuf
,
914 ok
= swrite1(sp
, data
,
921 if (sz
== sp
->s_wbufsize
) {
922 ok
= swrite1(sp
, data
, sp
->s_wbufsize
, -1);
926 memcpy(&sp
->s_wbuf
[sp
->s_wbufpos
], data
, sz
);
930 } else if (use_buffer
== 0 && sp
->s_wbuf
!= NULL
&&
934 if (swrite1(sp
, sp
->s_wbuf
, x
, -1) != OKAY
)
939 #if defined (USE_NSS)
941 x
= PR_Write(sp
->s_prfd
, data
, sz
);
943 #elif defined (USE_OPENSSL)
945 ssl_retry
: x
= SSL_write(sp
->s_ssl
, data
, sz
);
947 switch (SSL_get_error(sp
->s_ssl
, x
)) {
948 case SSL_ERROR_WANT_READ
:
949 case SSL_ERROR_WANT_WRITE
:
956 x
= xwrite(sp
->s_fd
, data
, sz
);
960 snprintf(o
, sizeof o
, "%s write error",
961 sp
->s_desc
? sp
->s_desc
: "socket");
962 #if defined (USE_NSS)
963 sp
->s_use_ssl
? nss_gen_err("%s", o
) : perror(o
);
964 #elif defined (USE_OPENSSL)
965 sp
->s_use_ssl
? ssl_gen_err("%s", o
) : perror(o
);
968 #endif /* !USE_SSL */
977 sgetline(char **line
, size_t *linesize
, size_t *linelen
, struct sock
*sp
)
986 if (*line
== NULL
|| lp
> &(*line
)[*linesize
- 128]) {
987 size_t diff
= lp
- *line
;
988 *line
= srealloc(*line
, *linesize
+= 256);
991 if (sp
->s_rbufptr
== NULL
||
992 sp
->s_rbufptr
>= &sp
->s_rbuf
[sp
->s_rsz
]) {
993 #if defined (USE_NSS)
995 if ((sp
->s_rsz
= PR_Read(sp
->s_prfd
,
997 sizeof sp
->s_rbuf
)) <= 0) {
1000 snprintf(o
, sizeof o
, "%s",
1004 nss_gen_err("%s", o
);
1009 #elif defined (USE_OPENSSL)
1010 if (sp
->s_use_ssl
) {
1011 ssl_retry
: if ((sp
->s_rsz
= SSL_read(sp
->s_ssl
,
1013 sizeof sp
->s_rbuf
)) <= 0) {
1014 if (sp
->s_rsz
< 0) {
1016 switch(SSL_get_error(sp
->s_ssl
,
1018 case SSL_ERROR_WANT_READ
:
1019 case SSL_ERROR_WANT_WRITE
:
1022 snprintf(o
, sizeof o
, "%s",
1026 ssl_gen_err("%s", o
);
1032 #endif /* USE_SSL */
1034 again
: if ((sp
->s_rsz
= read(sp
->s_fd
, sp
->s_rbuf
,
1035 sizeof sp
->s_rbuf
)) <= 0) {
1036 if (sp
->s_rsz
< 0) {
1040 snprintf(o
, sizeof o
, "%s",
1049 sp
->s_rbufptr
= sp
->s_rbuf
;
1051 } while ((*lp
++ = *sp
->s_rbufptr
++) != '\n');
1054 *linelen
= lp
- *line
;
1059 sopen(const char *xserver
, struct sock
*sp
, int use_ssl
,
1060 const char *uhp
, const char *portstr
, int verbose
)
1063 char hbuf
[NI_MAXHOST
];
1064 struct addrinfo hints
, *res0
, *res
;
1066 struct sockaddr_in servaddr
;
1067 struct in_addr
**pptr
;
1070 unsigned short port
= 0;
1074 char *server
= (char *)xserver
;
1078 if ((cp
= strchr(server
, ':')) != NULL
) {
1081 port
= strtol(portstr
, NULL
, 10);
1083 server
= salloc(cp
- xserver
+ 1);
1084 memcpy(server
, xserver
, cp
- xserver
);
1085 server
[cp
- xserver
] = '\0';
1088 memset(&hints
, 0, sizeof hints
);
1089 hints
.ai_socktype
= SOCK_STREAM
;
1091 fprintf(stderr
, "Resolving host %s . . .", server
);
1092 if (getaddrinfo(server
, portstr
, &hints
, &res0
) != 0) {
1093 fprintf(stderr
, catgets(catd
, CATSET
, 252,
1094 "Could not resolve host: %s\n"), server
);
1097 fprintf(stderr
, " done.\n");
1099 for (res
= res0
; res
!= NULL
&& sockfd
< 0; res
= res
->ai_next
) {
1101 if (getnameinfo(res
->ai_addr
, res
->ai_addrlen
,
1102 hbuf
, sizeof hbuf
, NULL
, 0,
1103 NI_NUMERICHOST
) != 0)
1104 strcpy(hbuf
, "unknown host");
1105 fprintf(stderr
, catgets(catd
, CATSET
, 192,
1106 "Connecting to %s:%s . . ."),
1109 if ((sockfd
= socket(res
->ai_family
, res
->ai_socktype
,
1110 res
->ai_protocol
)) >= 0) {
1111 if (connect(sockfd
, res
->ai_addr
, res
->ai_addrlen
)!=0) {
1118 perror(catgets(catd
, CATSET
, 254, "could not connect"));
1123 #else /* USE_IPV6 */
1125 if (strcmp(portstr
, "smtp") == 0)
1127 else if (strcmp(portstr
, "smtps") == 0)
1129 else if (strcmp(portstr
, "imap") == 0)
1131 else if (strcmp(portstr
, "imaps") == 0)
1133 else if (strcmp(portstr
, "pop3") == 0)
1135 else if (strcmp(portstr
, "pop3s") == 0)
1137 else if ((ep
= getservbyname((char *)portstr
, "tcp")) != NULL
)
1140 fprintf(stderr
, tr(251, "Unknown service: %s\n"),
1147 fprintf(stderr
, "Resolving host %s . . .", server
);
1148 if ((hp
= gethostbyname(server
)) == NULL
) {
1149 fprintf(stderr
, catgets(catd
, CATSET
, 252,
1150 "Could not resolve host: %s\n"), server
);
1153 fprintf(stderr
, " done.\n");
1154 pptr
= (struct in_addr
**)hp
->h_addr_list
;
1155 if ((sockfd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1) {
1156 perror(catgets(catd
, CATSET
, 253, "could not create socket"));
1159 memset(&servaddr
, 0, sizeof servaddr
);
1160 servaddr
.sin_family
= AF_INET
;
1161 servaddr
.sin_port
= port
;
1162 memcpy(&servaddr
.sin_addr
, *pptr
, sizeof(struct in_addr
));
1164 fprintf(stderr
, catgets(catd
, CATSET
, 192,
1165 "Connecting to %s:%d . . ."),
1166 inet_ntoa(**pptr
), ntohs(port
));
1167 if (connect(sockfd
, (struct sockaddr
*)&servaddr
, sizeof servaddr
)
1169 perror(catgets(catd
, CATSET
, 254, "could not connect"));
1172 #endif /* USE_IPV6 */
1174 fputs(catgets(catd
, CATSET
, 193, " connected.\n"), stderr
);
1175 memset(sp
, 0, sizeof *sp
);
1181 if ((ok
= ssl_open(server
, sp
, uhp
)) != OKAY
)
1188 #endif /* HAVE_SOCKETS */