1 /*************************************************************************
2  *  TinyFugue - programmable mud client
3  *  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2002, 2003, 2004, 2005, 2006-2007 Ken Keys
4  *
5  *  TinyFugue (aka "tf") is protected under the terms of the GNU
6  *  General Public License.  See the file "COPYING" for details.
7  ************************************************************************/
8 static const char RCSid[] = "$Id: socket.c,v 35004.288 2007/01/13 23:12:39 kkeys Exp $";
9 
10 
11 /***************************************************************
12  * Fugue socket handling
13  *
14  * Written by Ken Keys
15  * Reception and transmission through sockets is handled here.
16  * This module also contains the main loop.
17  * Multiple sockets handled here.
18  * Autologin handled here.
19  ***************************************************************/
20 
21 #include "tfconfig.h"
22 #include <sys/types.h>
23 #if HAVE_SYS_SELECT_H
24 # include <sys/select.h>
25 #endif
26 /* #include <sys/time.h> */
27 #include <fcntl.h>
28 #include <sys/file.h>	/* for FNONBLOCK on SVR4, hpux, ... */
29 #include <sys/socket.h>
30 #include <signal.h>	/* for killing resolver child process */
31 
32 #if HAVE_SSL
33 # include <openssl/ssl.h>
34 # include <openssl/err.h>
35     SSL_CTX *ssl_ctx;
36 #endif
37 
38 #ifdef NETINET_IN_H
39 # include NETINET_IN_H
40 #else
41 /* Last resort - we'll assume the "normal" stuff. */
42 struct in_addr {
43 	unsigned long	s_addr;
44 };
45 struct sockaddr_in {
46 	short		sin_family;
47 	unsigned short	sin_port;
48 	struct in_addr	sin_addr;
49 	char		sin_zero[8];
50 };
51 #define	htons(x)	(x)	/* assume big-endian machine */
52 #endif
53 
54 #ifdef ARPA_INET_H
55 # include ARPA_INET_H
56 #endif
57 
58 #if HAVE_MCCP
59 # include <zlib.h>
60 #endif
61 
62 #include "port.h"
63 #include "tf.h"
64 #include "util.h"
65 #include "pattern.h"
66 #include "search.h"
67 #include "tfio.h"
68 #include "tfselect.h"
69 #include "history.h"
70 #include "world.h"
71 #include "socket.h"
72 #include "output.h"
73 #include "attr.h"
74 #include "process.h"
75 #include "macro.h"
76 #include "keyboard.h"
77 #include "cmdlist.h"
78 #include "command.h"
79 #include "signals.h"
80 #include "variable.h"	/* set_var_by_*() */
81 
82 #ifdef _POSIX_VERSION
83 # include <sys/wait.h>
84 #endif
85 
86 #if !defined(AF_INET6) || !defined(IN6_ADDR) || !HAVE_GETADDRINFO
87 # undef ENABLE_INET6
88 # define ENABLE_INET6 0
89 #endif
90 
91 #ifndef INET_ADDRSTRLEN
92 #define INET_ADDRSTRLEN 16
93 #endif
94 #ifndef INET6_ADDRSTRLEN
95 #define INET6_ADDRSTRLEN 46
96 #endif
97 
98 #ifdef PLATFORM_OS2
99 # define NONBLOCKING_GETHOST
100 #endif
101 
102 #ifdef PLATFORM_UNIX
103 # ifndef __CYGWIN32__
104 #  if HAVE_WAITPID
105 #   define NONBLOCKING_GETHOST
106 #  endif
107 # endif
108 #endif
109 
110 #include NETDB_H
111 
112 #if !HAVE_GAI_STRERROR || !defined(AI_NUMERICHOST) || !defined(EAI_SERVICE)
113   /* System's implementation is incomplete.  Avoid it. */
114 # undef HAVE_GETADDRINFO
115 #endif
116 
117 #define TF_EAI_ADDRFAMILY  -1 /* address family for hostname not supported */
118 #define TF_EAI_AGAIN       -2 /* temporary failure in name resolution */
119 #define TF_EAI_BADFLAGS    -3 /* invalid value for ai_flags */
120 #define TF_EAI_FAIL        -4 /* non-recoverable failure in name resolution */
121 #define TF_EAI_FAMILY      -5 /* ai_family not supported */
122 #define TF_EAI_MEMORY      -6 /* memory allocation failure */
123 #define TF_EAI_NODATA      -7 /* no address associated with hostname */
124 #define TF_EAI_NONAME      -8 /* hostname nor servname provided, or not known */
125 #define TF_EAI_SERVICE     -9 /* servname not supported for ai_socktype */
126 #define TF_EAI_SOCKTYPE   -10 /* ai_socktype not supported */
127 #define TF_EAI_SYSTEM     -11 /* system error returned in errno */
128 #define TF_EAI_BADHINTS   -12
129 #define TF_EAI_PROTOCOL   -13
130 #define TF_EAI_MAX        -14
131 
132 static const char *tf_gai_errlist[] = {
133     "Error 0",
134     "address family for hostname not supported",
135     "temporary failure in name resolution",
136     "invalid value for ai_flags",
137     "non-recoverable failure in name resolution",
138     "ai_family not supported",
139     "memory allocation failure",
140     "no address associated with hostname",
141     "hostname nor servname provided, or not known",
142     "unknown service (port) name",
143     "ai_socktype not supported",
144     "system error returned in errno",
145 };
146 
147 #if HAVE_GETADDRINFO
148 /* The standard message for EAI_SERVICE is horrible.  We override it. */
149 # define gai_strerror(err) \
150     ((err) == EAI_SERVICE ? tf_gai_errlist[-TF_EAI_SERVICE] : (gai_strerror)(err))
151 
152 #else /* !HAVE_GETADDRINFO */
153 /* Partial implementation of getaddrinfo() and friends */
154 # define addrinfo tfaddrinfo
155 # define getaddrinfo tfgetaddrinfo
156 # define freeaddrinfo tffreeaddrinfo
157 
158 struct tfaddrinfo {
159     int     ai_flags;     /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
160     int     ai_family;    /* PF_xxx */
161     int     ai_socktype;  /* SOCK_xxx */
162     int     ai_protocol;  /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
163     size_t  ai_addrlen;   /* length of ai_addr */
164     char   *ai_canonname; /* canonical name for nodename */
165     struct sockaddr  *ai_addr; /* binary address */
166     struct addrinfo  *ai_next; /* next structure in linked list */
167 };
168 
169 #define AI_NUMERICHOST  0x00000004 /* prevent name resolution */
170 #define AI_ADDRCONFIG   0x00000400 /* only if any address is assigned */
171 
172 # if !HAVE_HSTRERROR
173 static const char *h_errlist[] = {
174     "Error 0",
175     "Unknown host",
176     "Host name lookup failure",
177     "Unknown server error",
178     "No address associated with name"
179 };
180 #  define hstrerror(err)  ((err) <= 4 ? h_errlist[(err)] : "unknown error")
181 # endif /* !HAVE_HSTRERROR */
182 
183 #if HAVE_H_ERRNO
184   /* extern int h_errno; */ /* this could conflict */
185 #elif !defined(h_errno)
186 # define h_errno 1
187 #endif
188 
189 # define gai_strerror(err) ((err) < 0 ? tf_gai_errlist[-(err)] : hstrerror(err))
190 
191 #endif /* !HAVE_GETADDRINFO */
192 
193 #ifdef NONBLOCKING_GETHOST
194 # ifndef PLATFORM_OS2
195 #  include <sys/uio.h> /* child uses writev() */
196 # endif
197   static void waitforhostname(int fd, const char *name, const char *port);
198   static int nonblocking_gethost(const char *name, const char *port,
199       struct addrinfo **addrs, pid_t *pidp, const char **what);
200 #endif
201 
202 #ifndef INADDR_NONE
203 # define INADDR_NONE 0xffffffff     /* should be in <netinet/in.h> */
204 #endif
205 
206 
207 /* Nonblocking connect.
208  * Legend for comment columns:
209  *      W = works, N = not defined, F = defined but fails, ? = unknown
210  * Nonblocking connect will work on a system if the column contains a 'W'
211  * and there is no 'F' above it; 'N' does not matter.  The order of the
212  * tests is arranged to keep the 'F's below the 'W's.
213  *
214  *                                                        S
215  *                                                        o
216  *                                      P           L  S  l     H
217  *                                      O     S     i  u  a  I  P
218  *                                      S  B  Y  A  n  n  r  R  /
219  *                                      I  S  S  I  u  O  i  I  U
220  *                                      X  D  V  X  x  S  s  X  X
221  */
222 #ifdef FNONBLOCK                     /* N  ?  W  W  N  ?  W  W  W */
223 # define TF_NONBLOCK FNONBLOCK
224 #else
225 # ifdef O_NONBLOCK                   /* W  ?  ?  W  W  ?  W  W  ? */
226 #  define TF_NONBLOCK O_NONBLOCK
227 # else
228 #  ifdef FNDELAY                     /* ?  W  ?  F  W  ?  W  W  ? */
229 #   define TF_NONBLOCK FNDELAY
230 #  else
231 #   ifdef O_NDELAY                   /* ?  W  ?  F  W  ?  W  W  ? */
232 #    define TF_NONBLOCK O_NDELAY
233 #   else
234 #    ifdef FNBIO                     /* ?  ?  W  N  N  F  N  N  ? */
235 #     define TF_NONBLOCK FNBIO
236 #    else
237 #     ifdef FNONBIO                  /* ?  ?  ?  N  N  F  N  N  ? */
238 #      define TF_NONBLOCK FNONBIO
239 #     else
240 #      ifdef FNONBLK                 /* ?  ?  ?  N  N  ?  N  W  ? */
241 #       define TF_NONBLOCK FNONBLK
242 #      else
243 #       define TF_NONBLOCK 0
244 #      endif
245 #     endif
246 #    endif
247 #   endif
248 #  endif
249 # endif
250 #endif
251 
252 
253 #ifdef TF_AIX_DECLS
254 extern int connect(int, struct sockaddr *, int);
255 #endif
256 
257 #if SOCKS
258 # ifndef SOCKS_NONBLOCK
259 #  define TF_NONBLOCK 0
260 # endif
261 #endif
262 
263 /* connection states */
264 typedef enum {
265     SS_NEW,		/* brand spanking new */
266     SS_RESOLVING,	/* hostname resolution is pending */
267     SS_RESOLVED,	/* hostname resolution is complete */
268     SS_CONNECTING,	/* connection is pending */
269     SS_CONNECTED,	/* connection is established */
270     SS_OPEN,		/* open, without a connection */
271     SS_ZOMBIE,		/* connection dead, but some text may be unseen */
272     SS_DEAD		/* connection dead, and all text has been seen */
273 } constate_t;
274 
275 /* flags */
276 #define SOCKLOGIN	0x01	/* autologin requested by user */
277 #define SOCKPROMPT	0x02	/* last prompt was definitely a prompt */
278 #define SOCKPROXY	0x04	/* indirect connection through proxy server */
279 #define SOCKTELNET	0x08	/* server supports telnet protocol */
280 #define SOCKMAYTELNET	0x10	/* server might support telnet protocol */
281 #define SOCKCOMPRESS	0x20	/* server has enabled MCCP v1 or v2 */
282 #define SOCKALLOCADDRS	0x40	/* addrs allocated by tf, not getaddrinfo */
283 #define SOCKECHO	0x80	/* receive all sent text (loopback) */
284 
285 VEC_TYPEDEF(telnet_opts, 256);
286 
287 typedef struct Sock {		/* an open connection to a server */
288     int fd;			/* socket to server, or pipe to name resolver */
289     const char *host, *port;	/* server address, human readable */
290     struct addrinfo *addrs;	/* possible server addresses */
291     struct addrinfo *addr;	/* actual server address */
292     const char *myhost;		/* explicit client address, human readable */
293     struct addrinfo *myaddr;	/* explicit client address */
294     telnet_opts tn_us;		/* our telnet options */
295     telnet_opts tn_us_tog;	/* our telnet options we want changed */
296     telnet_opts tn_them;	/* server's telnet options */
297     telnet_opts tn_them_tog;	/* server's telnet options we want changed */
298     constate_t constate;	/* connection state */
299     unsigned char flags;	/* SOCK* flags */
300     short numquiet;		/* # of lines to gag after connecting */
301     struct World *world;	/* world to which socket is connected */
302     struct Sock *next, *prev;	/* next/prev sockets in linked list */
303     Stringp buffer;		/* buffer for incoming characters */
304     Stringp subbuffer;		/* buffer for incoming characters */
305     Queue queue;		/* queue of incoming lines */
306     conString *prompt;		/* prompt from server */
307     struct timeval prompt_timeout; /* when does unterm'd line become a prompt */
308     int ttype;			/* index into enum_ttype[] */
309     attr_t attrs;		/* current text attributes */
310     attr_t prepromptattrs;	/* text attributes before implicit prompt */
311     unsigned long alert_id;	/* id of last alert on this socket */
312     struct timeval time[2];	/* time of last receive/send */
313     char fsastate;		/* parser finite state automaton state */
314     char substate;		/* parser fsa state for telnet subnegotiation */
315     pid_t pid;			/* OS pid of name resolution process */
316 #if HAVE_MCCP
317     z_stream *zstream;		/* state of compressed stream */
318 #endif
319 #if HAVE_SSL
320     SSL *ssl;			/* SSL state */
321 #endif
322 } Sock;
323 
324 typedef struct {
325     int err;
326     size_t size;
327 } nbgai_hdr_t;
328 
329 static Sock *find_sock(const char *name);
330 static void  wload(World *w);
331 static int   fg_sock(Sock *sock, int quiet);
332 static int   get_host_address(Sock *sock, const char **what, int *errp);
333 #if !HAVE_GETADDRINFO
334 static int   tfgetaddrinfo(const char *nodename, const char *port,
335 	     const struct addrinfo *hints, struct addrinfo **res);
336 #endif
337 static int   opensock(World *world, int flags);
338 static int   openconn(Sock *new);
339 static int   establish(Sock *new);
340 #if 0
341 static void  fg_live_sock(void);
342 #endif
343 static void  nuke_dead_socks(void);
344 static void  nukesock(Sock *sock);
345 static void  handle_prompt(String *str, int offset, int confirmed);
346 static void  handle_implicit_prompt(void);
347 static void  unprompt(Sock *sock, int update);
348 static void  test_prompt(void);
349 static void  schedule_prompt(Sock *sock);
350 static void  handle_socket_lines(void);
351 static int   handle_socket_input(const char *simbuffer, int simlen);
352 static int   transmit(const char *s, unsigned int len);
353 static void  telnet_send(String *cmd);
354 static void  telnet_subnegotiation(void);
355 static void  f_telnet_recv(int cmd, int opt);
356 static int   is_quiet(const char *str);
357 static int   is_bamf(const char *str);
358 static void  do_naws(Sock *sock);
359 static void  telnet_debug(const char *dir, const char *str, int len);
360 static void  preferred_telnet_options(void);
361 static void  killsock(Sock *sock);
362 
363 #define zombiesock(sock)	killsock(sock)
364 #define flushxsock() \
365     do { if (xsock->queue.list.head) handle_socket_lines(); } while (0)
366 
367 #define telnet_recv(cmd, opt)	f_telnet_recv((UCHAR)cmd, (UCHAR)opt);
368 #define no_reply(str) telnet_debug("sent", "[no reply (" str ")", 0)
369 
370 #ifndef CONN_WAIT
371 #define CONN_WAIT 400000
372 #endif
373 
374 #ifndef PROC_WAIT
375 #define PROC_WAIT 100000
376 #endif
377 
378 #define SPAM (4*1024)		/* break loop if this many chars are received */
379 
380 static fd_set readers;		/* input file descriptors */
381 static fd_set active;		/* active file descriptors */
382 static fd_set writers;		/* pending connections */
383 static fd_set connected;	/* completed connections */
384 static unsigned int nfds;	/* max # of readers/writers */
385 static Sock *hsock = NULL;	/* head of socket list */
386 static Sock *tsock = NULL;	/* tail of socket list */
387 static Sock *fsock = NULL;	/* foreground socket */
388 static int dead_socks = 0;	/* Number of unnuked dead sockets */
389 static int socks_with_lines = 0;/* Number of socks with queued received lines */
390 static struct timeval prompt_timeout = {0,0};
391 static const char *telnet_label[0x100];
392 STATIC_BUFFER(telbuf);
393 
394 #define MAXQUIET        25	/* max # of lines to suppress during login */
395 
396 /* Note: many telnet servers send DO ECHO and DO SGA together to mean
397  * character-at-a-time mode.
398  */
399 
400 /* TELNET special characters (RFC 854) */
401 #define TN_EOR		((char)239)	/* end of record (RFC 885) */
402 #define TN_SE		((char)240)	/* subnegotiation end */
403 #define TN_NOP		((char)241)	/* no operation */
404 #define TN_DATA_MARK	((char)242)	/* (not used) */
405 #define TN_BRK		((char)243)	/* break (not used) */
406 #define TN_IP		((char)244)	/* interrupt process (not used) */
407 #define TN_AO		((char)245)	/* abort output (not used) */
408 #define TN_AYT		((char)246)	/* are you there? (not used) */
409 #define TN_EC		((char)247)	/* erase character (not used) */
410 #define TN_EL		((char)248)	/* erase line (not used) */
411 #define TN_GA		((char)249)	/* go ahead */
412 #define TN_SB		((char)250)	/* subnegotiation begin */
413 #define TN_WILL		((char)251)	/* I offer to ~, or ack for DO */
414 #define TN_WONT		((char)252)	/* I will stop ~ing, or nack for DO */
415 #define TN_DO		((char)253)	/* Please do ~?, or ack for WILL */
416 #define TN_DONT		((char)254)	/* Stop ~ing!, or nack for WILL */
417 #define TN_IAC		((char)255)	/* telnet Is A Command character */
418 
419 /* TELNET options (RFC 855) */		/* RFC# - description */
420 #define TN_BINARY	((char)0)	/*  856 - transmit binary */
421 #define TN_ECHO		((char)1)	/*  857 - echo */
422 #define TN_SGA		((char)3)	/*  858 - suppress GA (not used) */
423 #define TN_STATUS	((char)5)	/*  859 - (not used) */
424 #define TN_TIMING_MARK	((char)6)	/*  860 - (not used) */
425 #define TN_TTYPE	((char)24)	/* 1091 - terminal type */
426 #define TN_SEND_EOR	((char)25)	/*  885 - transmit EOR */
427 #define TN_NAWS		((char)31)	/* 1073 - negotiate about window size */
428 #define TN_TSPEED	((char)32)	/* 1079 - terminal speed (not used) */
429 #define TN_FLOWCTRL	((char)33)	/* 1372 - (not used) */
430 #define TN_LINEMODE	((char)34)	/* 1184 - (not used) */
431 #define TN_XDISPLOC	((char)35)	/* 1096 - (not used) */
432 #define TN_ENVIRON	((char)36)	/* 1408 - (not used) */
433 #define TN_AUTH		((char)37)	/* 1416 - (not used) */
434 #define TN_NEW_ENVIRON	((char)39)	/* 1572 - (not used) */
435 #define TN_CHARSET	((char)42)	/* 2066 - (not used) */
436 /* 85 & 86 are not standard.  See http://www.randomly.org/projects/MCCP/ */
437 #define TN_COMPRESS	((char)85)	/* MCCP v1 */
438 #define TN_COMPRESS2	((char)86)	/* MCCP v2 */
439 
440 #define UCHAR		unsigned char
441 
442 #define tn_send_opt(cmd, opt) \
443     ( Sprintf(telbuf, "%c%c%c", TN_IAC, (cmd), (opt)), telnet_send(telbuf) )
444 
445 #define TELOPT(sock, field, opt) \
446 	VEC_ISSET((UCHAR)(opt), &(sock)->tn_ ## field)
447 #define SET_TELOPT(sock, field, opt) \
448 	VEC_SET((UCHAR)(opt), &(sock)->tn_ ## field)
449 #define CLR_TELOPT(sock, field, opt) \
450 	VEC_CLR((UCHAR)(opt), &(sock)->tn_ ## field)
451 
452 #define DO(opt)		( tn_send_opt(TN_DO,   (opt)) )
453 #define DONT(opt)	( tn_send_opt(TN_DONT, (opt)) )
454 #define WILL(opt)	( tn_send_opt(TN_WILL, (opt)) )
455 #define WONT(opt)	( tn_send_opt(TN_WONT, (opt)) )
456 
457 #define ANSI_CSI	'\233'	/* ANSI terminal Command Sequence Intro */
458 
459 #if HAVE_MCCP /* hack for broken MCCPv1 subnegotiation */
460 char mccp1_subneg[] = { TN_IAC, TN_SB, TN_COMPRESS, TN_WILL, TN_SE };
461 #endif
462 
463 Sock *xsock = NULL;		/* current (transmission) socket */
464 int quit_flag = FALSE;		/* Are we all done? */
465 int active_count = 0;		/* # of (non-current) active sockets */
466 String *incoming_text = NULL;
467 const int feature_IPv6 = ENABLE_INET6 - 0;
468 const int feature_MCCPv1 = HAVE_MCCP - 0;
469 const int feature_MCCPv2 = HAVE_MCCP - 0;
470 const int feature_ssl = HAVE_SSL - 0;
471 const int feature_SOCKS = SOCKS - 0;
472 
473 static const char *CONFAIL_fmt = "%% Connection to %s failed: %s: %s";
474 static const char *ICONFAIL_fmt = "%% Intermediate connection to %s failed: %s: %s";
475 
476 #define ICONFAIL_AI(sock, why) \
477     ICONFAIL((sock), printai((sock)->addr, NULL), (why))
478 
479 #define CONFAILHP(sock, why) \
480 do { \
481     do_hook(H_CONFAIL, "%% Unable to connect to %s: %s %s: %s", "%s %s %s: %s", \
482         (sock)->world->name, (sock)->world->host, (sock)->world->port, (why)); \
483     oflush(); \
484 } while (0)
485 
486 #define CONFAIL(sock, what, why) \
487 do { \
488     do_hook(H_CONFAIL, CONFAIL_fmt, "%s %s %s", \
489 	(sock)->world->name, (what), (why)); \
490     oflush(); \
491 } while (0)
492 
493 #define DISCON(where, what, why) \
494     do_hook(H_DISCONNECT, "%% Connection to %s closed: %s: %s", "%s %s: %s", \
495 	where, what, why)
496 
497 #define ROUND_UP_LENGTH(len)	((len + 7) & -8)
498 
499 #if HAVE_SSL
ssl_err(const char * str)500 static void ssl_err(const char *str)
501 {
502     unsigned long e;
503     while ((e = ERR_get_error()))
504 	eprintf("%s: %s", str, ERR_error_string(e, NULL));
505 }
506 
ssl_io_err(Sock * sock,int ret,int hook)507 static void ssl_io_err(Sock *sock, int ret, int hook)
508 {
509     /* NB: sock->addr may have already been changed by setupnextconn() */
510     int err;
511     const char *fmt;
512 
513     flushxsock();
514 
515     switch (hook) {
516     case H_CONFAIL: fmt = CONFAIL_fmt; break;
517     case H_ICONFAIL: fmt = ICONFAIL_fmt; break;
518     case H_DISCONNECT: fmt = "%% Connection to %s closed: %s: %s"; break;
519     }
520 
521 #define ssl_io_err_hook(what, why) \
522     do_hook(hook, fmt, "%s %s %s", xsock->world->name, what, why);
523 
524     err = SSL_get_error(sock->ssl, ret);
525     switch (err) {
526     case SSL_ERROR_NONE:
527 	break;
528     case SSL_ERROR_ZERO_RETURN:
529 	ssl_io_err_hook("SSL", "SSL_ERROR_ZERO_RETURN");
530 	break;
531     case SSL_ERROR_WANT_READ:
532 	ssl_io_err_hook("SSL", "SSL_ERROR_WANT_READ");
533 	break;
534     case SSL_ERROR_WANT_WRITE:
535 	ssl_io_err_hook("SSL", "SSL_ERROR_WANT_WRITE");
536 	break;
537     case SSL_ERROR_WANT_CONNECT:
538 	ssl_io_err_hook("SSL", "SSL_ERROR_WANT_CONNECT");
539 	break;
540     case SSL_ERROR_SYSCALL:
541 	if (ret == 0) {
542 	    ssl_io_err_hook("SSL/system", "invalid EOF");
543 	} else if (ret == -1) {
544 	    ssl_io_err_hook("SSL/system", strerror(errno));
545 	} else {
546 	    while ((err = ERR_get_error())) {
547 		ssl_io_err_hook("SSL/system", ERR_error_string(err, NULL));
548 	    }
549 	}
550 	break;
551     case SSL_ERROR_SSL:
552 	while ((err = ERR_get_error())) {
553 	    ssl_io_err_hook("SSL/lib", ERR_error_string(err, NULL));
554 	}
555 	break;
556     }
557 }
558 
init_ssl(void)559 static void init_ssl(void)
560 {
561     SSL_load_error_strings();
562     SSL_library_init();
563     /* XXX seed PRNG */
564     ssl_ctx = SSL_CTX_new(SSLv23_client_method());
565     if (!ssl_ctx) {
566 	ssl_err("SSL_CTX_new");
567 	return;
568     }
569     if (!SSL_CTX_set_cipher_list(ssl_ctx, "ALL")) {
570 	ssl_err("SSL_CTX_set_cipher_list");
571 	return;
572     }
573 }
574 #endif
575 
576 /* initialize socket.c data */
init_sock(void)577 void init_sock(void)
578 {
579     int i;
580 
581     FD_ZERO(&readers);
582     FD_ZERO(&active);
583     FD_ZERO(&writers);
584     FD_ZERO(&connected);
585     FD_SET(STDIN_FILENO, &readers);
586     nfds = 1;
587 
588     set_var_by_id(VAR_async_conn, !!TF_NONBLOCK);
589 #ifdef NONBLOCKING_GETHOST
590     set_var_by_id(VAR_async_name, 1);
591 #endif
592 
593     for (i = 0; i < 0x100; i++) telnet_label[i] = NULL;
594 
595     telnet_label[(UCHAR)TN_BINARY]	= "BINARY";
596     telnet_label[(UCHAR)TN_ECHO]	= "ECHO";
597     telnet_label[(UCHAR)TN_SGA]		= "SUPPRESS-GO-AHEAD";
598     telnet_label[(UCHAR)TN_STATUS]	= "STATUS";
599     telnet_label[(UCHAR)TN_TIMING_MARK]	= "TIMING-MARK";
600     telnet_label[(UCHAR)TN_TTYPE]	= "TERMINAL-TYPE";
601     telnet_label[(UCHAR)TN_SEND_EOR]	= "SEND-EOR";
602     telnet_label[(UCHAR)TN_NAWS]	= "NAWS";
603     telnet_label[(UCHAR)TN_TSPEED]	= "TSPEED";
604     telnet_label[(UCHAR)TN_FLOWCTRL]	= "TOGGLE-FLOW-CONTROL";
605     telnet_label[(UCHAR)TN_LINEMODE]	= "LINEMODE";
606     telnet_label[(UCHAR)TN_XDISPLOC]	= "XDISPLOC";
607     telnet_label[(UCHAR)TN_ENVIRON]	= "ENVIRON";
608     telnet_label[(UCHAR)TN_AUTH]	= "AUTHENTICATION";
609     telnet_label[(UCHAR)TN_NEW_ENVIRON]	= "NEW-ENVIRON";
610     telnet_label[(UCHAR)TN_CHARSET]	= "CHARSET";
611     telnet_label[(UCHAR)TN_COMPRESS]	= "COMPRESS";
612     telnet_label[(UCHAR)TN_COMPRESS2]	= "COMPRESS2";
613     telnet_label[(UCHAR)TN_EOR]		= "EOR";
614     telnet_label[(UCHAR)TN_SE]		= "SE";
615     telnet_label[(UCHAR)TN_NOP]		= "NOP";
616     telnet_label[(UCHAR)TN_DATA_MARK]	= "DATA-MARK";
617     telnet_label[(UCHAR)TN_BRK]		= "BRK";
618     telnet_label[(UCHAR)TN_IP]		= "IP";
619     telnet_label[(UCHAR)TN_AO]		= "AO";
620     telnet_label[(UCHAR)TN_AYT]		= "AYT";
621     telnet_label[(UCHAR)TN_EC]		= "EC";
622     telnet_label[(UCHAR)TN_EL]		= "EL";
623     telnet_label[(UCHAR)TN_GA]		= "GA";
624     telnet_label[(UCHAR)TN_SB]		= "SB";
625     telnet_label[(UCHAR)TN_WILL]	= "WILL";
626     telnet_label[(UCHAR)TN_WONT]	= "WONT";
627     telnet_label[(UCHAR)TN_DO]		= "DO";
628     telnet_label[(UCHAR)TN_DONT]	= "DONT";
629     telnet_label[(UCHAR)TN_IAC]		= "IAC";
630 
631 #if HAVE_SSL
632     init_ssl();
633 #endif
634 }
635 
636 #define set_min_earliest(tv) \
637     do { \
638 	if (earliest.tv_sec == 0 || (tvcmp(&tv, &earliest) < 0)) { \
639 	    earliest = tv; \
640 	} \
641     } while (0)
642 
643 /* main_loop
644  * Here we mostly sit in select(), waiting for something to happen.
645  * The select timeout is set for the earliest process, mail check,
646  * or refresh event.  Signal processing and garbage collection is
647  * done at the beginning of each loop, where we're in a "clean" state.
648  */
main_loop(void)649 void main_loop(void)
650 {
651     static struct timeval now, earliest;    /* static, for recursion */
652     Sock *sock = NULL;		/* loop index */
653     static int count;		/* select count; remembered across recursion */
654     int received;
655     Sock *stopsock;
656     static int depth = 0;
657     struct timeval tv, *tvp;
658     struct timeval refresh_tv;
659     STATIC_STRING(low_memory_msg,
660 	"% WARNING: memory is low.  Try reducing history sizes.", 0);
661 
662     depth++;
663     while (!quit_flag) {
664         if (depth > 1 && interrupted()) break;
665 
666         /* deal with pending signals */
667         /* at loop beginning in case of signals before main_loop() */
668         process_signals();
669 
670         /* run processes */
671         /* at loop beginning in case of processes before main_loop() */
672         gettime(&now);
673         if (proctime.tv_sec && tvcmp(&proctime, &now) <= 0)
674 	    runall(0, NULL); /* run timed processes */
675 
676         if (low_memory_warning) {
677             low_memory_warning = 0;
678 	    tfputline(low_memory_msg, tferr);
679         }
680 
681         if (quit_flag) break;
682 
683         /* figure out when next event is so select() can timeout then */
684         gettime(&now);
685         earliest = proctime;
686 #if 1 /* XXX debugging */
687 	{
688 	    Sock *s;
689 	    int n = 0;
690 	    for (s = hsock; s; s = s->next)
691 		if (s->queue.list.head) n++;
692 	    if (n != socks_with_lines) {
693 		internal_error(__FILE__, __LINE__,
694 		    "socks_with_lines (%d) is not correct (%d)!",
695 		    socks_with_lines, n);
696 		socks_with_lines = n;
697 	    }
698 	}
699 #endif
700 	if (socks_with_lines)
701 	    earliest = now;
702         if (maillist && tvcmp(&maildelay, &tvzero) > 0) {
703             if (tvcmp(&now, &mail_update) >= 0) {
704                 check_mail();
705                 tvadd(&mail_update, &now, &maildelay);
706             }
707 	    set_min_earliest(mail_update);
708         }
709         if (visual && alert_timeout.tv_sec > 0) {
710             if (tvcmp(&alert_timeout, &now) < 0) {
711 		clear_alert();
712 	    } else {
713 		set_min_earliest(alert_timeout);
714             }
715 	}
716         if (visual && clock_update.tv_sec > 0) {
717             if (now.tv_sec >= clock_update.tv_sec)
718                 update_status_field(NULL, STAT_CLOCK);
719 	    set_min_earliest(clock_update);
720         }
721         if (prompt_timeout.tv_sec > 0) {
722 	    set_min_earliest(prompt_timeout);
723 	}
724 
725         /* flush pending display_screen output */
726         /* must be after all possible output and before select() */
727         oflush();
728 
729         if (pending_input || pending_line) {
730             tvp = &tv;
731             tv = tvzero;
732         } else if (earliest.tv_sec) {
733             tvp = &tv;
734             if (tvcmp(&earliest, &now) <= 0) {
735                 tv = tvzero;
736             } else {
737                 tvsub(&tv, &earliest, &now);
738 #if !HAVE_GETTIMEOFDAY
739                 /* We can't read microseconds, so we get within the right
740                  * second and then start polling. */
741                 if (proctime.tv_sec) {
742                     if ((--tv.tv_sec) == 0)
743                         tv.tv_usec = PROC_WAIT;
744                 }
745 #endif
746             }
747         } else tvp = NULL;
748 
749         if (need_refresh) {
750             if (!visual) {
751                 refresh_tv.tv_sec = refreshtime / 1000000;
752                 refresh_tv.tv_usec = refreshtime % 1000000;
753             } else {
754                 refresh_tv = tvzero;
755             }
756 
757             if (!tvp || refresh_tv.tv_sec < tvp->tv_sec ||
758                 (refresh_tv.tv_sec == tvp->tv_sec &&
759                 refresh_tv.tv_usec < tvp->tv_usec))
760             {
761                 tvp = &refresh_tv;
762             }
763         }
764 
765         if (visual && need_more_refresh) {
766             if (!tvp || 1 < tvp->tv_sec ||
767                 (1 == tvp->tv_sec && 0 < tvp->tv_usec))
768             {
769                 refresh_tv.tv_sec = 1;
770                 refresh_tv.tv_usec = 0;
771                 tvp = &refresh_tv;
772             }
773         }
774 
775         /* Wait for next event.
776          *   descriptor read:	user input, socket input, or /quote !
777          *   descriptor write:	nonblocking connect()
778          *   timeout:		time for runall() or do_refresh()
779          * Note: if the same descriptor appears in more than one fd_set, some
780          * systems count it only once, some count it once for each occurance.
781          */
782         active = readers;
783         connected = writers;
784         count = tfselect(nfds, &active, &connected, NULL, tvp);
785 
786         if (count < 0) {
787             /* select() must have exited due to error or interrupt. */
788             if (errno != EINTR) core(strerror(errno), __FILE__, __LINE__, 0);
789             /* In case we're in a kb tfgetS(), clear things for parent loop. */
790             FD_ZERO(&active);
791             FD_ZERO(&connected);
792 	    /* In case the dreaded solaris select bug caused tf to remove stdin
793 	     * from readers, user will probably panic and hit ^C, so we add
794 	     * stdin back to readers, and recover. */
795 	    FD_SET(STDIN_FILENO, &readers);
796 
797         } else {
798             if (count == 0) {
799                 /* select() must have exited due to timeout. */
800                 do_refresh();
801             }
802 
803             /* check for user input */
804             if (pending_input || FD_ISSET(STDIN_FILENO, &active)) {
805                 if (FD_ISSET(STDIN_FILENO, &active)) count--;
806                 do_refresh();
807                 if (!handle_keyboard_input(FD_ISSET(STDIN_FILENO, &active))) {
808                     /* input is at EOF, stop reading it */
809                     FD_CLR(STDIN_FILENO, &readers);
810                 }
811             }
812 
813             /* Check for socket completion/activity.  We pick up where we
814              * left off last time, so sockets near the end of the list aren't
815              * starved.  We stop when we've gone through the list once, or
816              * when we've received a lot of data (so spammy sockets don't
817              * degrade interactive response too much).
818              */
819             if (hsock) {
820                 received = 0;
821                 if (!sock) sock = hsock;
822                 stopsock = sock;
823 		/* note: count may have been zeroed by nested main_loop */
824                 while (count > 0 || socks_with_lines > 0 ||
825 		    prompt_timeout.tv_sec > 0)
826 		{
827                     xsock = sock;
828                     if (sock->constate >= SS_OPEN) {
829                         /* do nothing */
830                     } else if (FD_ISSET(xsock->fd, &connected)) {
831                         count--;
832                         establish(xsock);
833                     } else if (FD_ISSET(xsock->fd, &active)) {
834                         count--;
835                         if (xsock->constate == SS_RESOLVING) {
836                             openconn(xsock);
837                         } else if (xsock->constate == SS_CONNECTING) {
838                             establish(xsock);
839                         } else if (xsock == fsock || background) {
840                             received += handle_socket_input(NULL, 0);
841                         } else {
842                             FD_CLR(xsock->fd, &readers);
843                         }
844                     }
845 		    if (xsock->queue.list.head)
846 			handle_socket_lines();
847 
848 		    /* If there's a partial line that's past prompt_timeout,
849 		     * make it a prompt. */
850 		    if (xsock->prompt_timeout.tv_sec) {
851 			gettime(&now);
852 			if (tvcmp(&xsock->prompt_timeout, &now) < 0) {
853 			    handle_implicit_prompt();
854 			}
855 		    }
856 
857                     sock = sock->next ? sock->next : hsock;
858 		    if (sock == stopsock || received >= SPAM) break;
859                 }
860 
861                 /* fsock and/or xsock may have changed during loop above. */
862                 xsock = fsock;
863 
864 		if (prompt_timeout.tv_sec > 0) {
865 		    /* reset global prompt timeout */
866 		    Sock *psock;
867 		    prompt_timeout = tvzero;
868 		    for (psock = hsock; psock; psock = psock->next) {
869 			schedule_prompt(psock);
870 		    }
871 		}
872             }
873 
874 #if !NO_PROCESS
875             /* other active fds must be from command /quotes. */
876             if (count) gettime(&proctime);
877 #endif
878         }
879 
880         if (pending_line && read_depth) {    /* end of tf read() */
881             pending_line = FALSE;
882             break;
883         }
884 
885 #if 0
886         if (fsock && fsock->constate >= SS_ZOMBIE && auto_fg &&
887 	    !(fsock->world->screen->nnew || fsock->queue.list.head))
888 	{
889             fg_live_sock();
890         }
891 #endif
892 
893         /* garbage collection */
894         if (depth == 1) {
895             if (sock && sock->constate == SS_DEAD) sock = NULL;
896             if (dead_socks) nuke_dead_socks(); /* at end in case of quitdone */
897             nuke_dead_macros();
898             nuke_dead_procs();
899         }
900     }
901 
902     /* end of loop */
903     if (!--depth) {
904 	fsock = NULL;
905 	xsock = NULL;
906         while (hsock) nukesock(hsock);
907 #if HAVE_SSL
908 	SSL_CTX_free(ssl_ctx);
909 #endif
910     }
911 
912     /* If exiting recursive main_loop, count, active, and connected in the
913      * parent main_loop are invalid.  Set count to 0 to indicate that. */
914     count = 0;
915 }
916 
sockecho(void)917 int sockecho(void)
918 {
919     return !xsock || (xsock && !TELOPT(xsock, them, TN_ECHO));
920 }
921 
close_all(void)922 void close_all(void)
923 {
924     while (nfds > 3)
925 	close(--nfds);
926 }
927 
is_active(int fd)928 int is_active(int fd)
929 {
930     return FD_ISSET(fd, &active);
931 }
932 
readers_clear(int fd)933 void readers_clear(int fd)
934 {
935     FD_CLR(fd, &readers);
936 }
937 
readers_set(int fd)938 void readers_set(int fd)
939 {
940     FD_SET(fd, &readers);
941     if (fd >= nfds) nfds = fd + 1;
942 }
943 
tog_bg(Var * var)944 int tog_bg(Var *var)
945 {
946     Sock *sock;
947     if (background)
948         for (sock = hsock; sock; sock = sock->next)
949             if (sock->constate == SS_CONNECTED)
950                 FD_SET(sock->fd, &readers);
951     return 1;
952 }
953 
tog_keepalive(Var * var)954 int tog_keepalive(Var *var)
955 {
956     Sock *sock;
957     int flags;
958 
959     flags = keepalive;
960     for (sock = hsock; sock; sock = sock->next) {
961 	if (sock->constate != SS_CONNECTED) continue;
962 	if (setsockopt(sock->fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&flags,
963 	    sizeof(flags)) < 0)
964 	{
965 	    wprintf("setsockopt KEEPALIVE: %s", strerror(errno));
966 	}
967     }
968     return 1;
969 }
970 
971 /* get name of foreground world */
fgname(void)972 const char *fgname(void)
973 {
974     return fsock ? fsock->world->name : NULL;
975 }
976 
977 /* get current operational world */
xworld(void)978 World *xworld(void)
979 {
980     return xsock ? xsock->world : NULL;
981 }
982 
xsock_is_fg(void)983 int xsock_is_fg(void)
984 {
985     return xsock == fsock;
986 }
987 
have_active_socks(void)988 int have_active_socks(void)
989 {
990     Sock *sock;
991 
992     for (sock = hsock; sock; sock = sock->next) {
993 	if (sock->world->screen->nnew || sock->queue.list.head)
994 	    return 1;
995     }
996     return 0;
997 }
998 
999 /* set alert_id on xsock, so fg_sock can decide whether to clear alert */
xsock_alert_id(void)1000 void xsock_alert_id(void)
1001 {
1002     if (xsock)
1003 	xsock->alert_id = alert_id;
1004 }
1005 
socktime(const char * name,int dir)1006 struct timeval *socktime(const char *name, int dir)
1007 {
1008     Sock *sock;
1009     sock = *name ? find_sock(name) : xsock;
1010     if (!sock) return NULL;
1011     return &sock->time[dir];
1012 }
1013 
find_sock(const char * name)1014 static Sock *find_sock(const char *name)
1015 {
1016     Sock *sock;
1017 
1018     /* It is possible to (briefly) have multiple sockets with the same name,
1019      * if at most one is alive.  The alive socket is the most interesting,
1020      * and it will be closer to the tail, so we search backwards.
1021      */
1022     for (sock = tsock; sock; sock = sock->prev)
1023         if (sock->world && cstrcmp(sock->world->name, name) == 0)
1024             return sock;
1025     return NULL;
1026 }
1027 
1028 /* load macro file for a world */
wload(World * w)1029 static void wload(World *w)
1030 {
1031     const char *mfile;
1032     if (restriction >= RESTRICT_FILE) return;
1033     if ((mfile = world_mfile(w)))
1034         do_file_load(mfile, FALSE);
1035 }
1036 
world_hook(const char * fmt,const char * name)1037 int world_hook(const char *fmt, const char *name)
1038 {
1039     return do_hook(H_WORLD, virtscreen ? NULL : fmt, "%s",
1040 	name ? name : "");
1041 }
1042 
1043 /* bring a socket into the foreground */
fg_sock(Sock * sock,int quiet)1044 static int fg_sock(Sock *sock, int quiet)
1045 {
1046     static int depth = 0;
1047 
1048     if (depth) {
1049         eprintf("illegal reentry");
1050         return 0;
1051     }
1052 
1053     if (sockecho() != (!sock || !TELOPT(sock, them, TN_ECHO)))
1054         set_refresh_pending(REF_LOGICAL);
1055 
1056     xsock = sock;
1057     if (sock == fsock) return 2;  /* already there */
1058 
1059     if (fsock) {                          /* the socket being backgrounded... */
1060 	/* ...has new text */
1061         if (fsock->world->screen->nnew || fsock->queue.list.head) {
1062 	    fsock->world->screen->active = 1;
1063             ++active_count;
1064             update_status_field(NULL, STAT_ACTIVE);
1065 	/* ...is dead, with all text seen */
1066         } else if (fsock->constate == SS_ZOMBIE) {
1067             fsock->constate = SS_DEAD;
1068 	    dead_socks++;
1069 	}
1070     }
1071     fsock = sock;
1072     depth++;
1073 
1074     if (!virtscreen) update_status_field(NULL, STAT_WORLD);
1075     hide_screen(NULL);
1076 
1077     if (sock) {
1078 	if (sock->alert_id == alert_id) {
1079 	    clear_alert();
1080 	    sock->alert_id = 0;
1081 	}
1082 	if (sock->constate == SS_CONNECTED)
1083 	    FD_SET(sock->fd, &readers);
1084         if (sock->world->screen->active) {
1085 	    sock->world->screen->active = 0;
1086             --active_count;
1087             update_status_field(NULL, STAT_ACTIVE);
1088         }
1089         fg_screen = sock->world->screen;
1090 	unhide_screen(fg_screen); /* must do before hook which might oflush */
1091         world_hook((sock->constate >= SS_ZOMBIE) ?
1092             "---- World %s (dead) ----" : "---- World %s ----",
1093            sock->world->name);
1094 	switch_screen(quiet || !bg_output);
1095         tog_lp(NULL);
1096         update_prompt(sock->prompt, 1);
1097         if (sockmload) wload(sock->world);
1098     } else {
1099         fg_screen = default_screen;
1100 	unhide_screen(fg_screen);
1101         world_hook("---- No world ----", NULL);
1102 	switch_screen(quiet || !bg_output);
1103         update_prompt(NULL, 1);
1104     }
1105     depth--;
1106     return 1;
1107 }
1108 
handle_fg_command(String * args,int offset)1109 struct Value *handle_fg_command(String *args, int offset)
1110 {
1111     int opt, nosock = FALSE, noerr = FALSE, quiet = FALSE;
1112     int num = 0;
1113     ValueUnion uval;
1114     Sock *sock;
1115 
1116     startopt(CS(args), "nlqs<>c#");
1117     while ((opt = nextopt(NULL, &uval, NULL, &offset))) {
1118         switch (opt) {
1119         case 'n':  nosock = TRUE;  break;
1120         case 's':  noerr = TRUE;  break;
1121         case 'l':  break;  /* accepted and ignored */
1122         case 'q':  quiet = TRUE; break;
1123         case '<':  num = -1;  break;
1124         case '>':  num =  1;  break;
1125         case 'c':  num = uval.ival; break;
1126         default:   return shareval(val_zero);
1127         }
1128     }
1129 
1130     if (nosock) {
1131         return newint(fg_sock(NULL, quiet));
1132 
1133     } else if (num) {
1134         Sock *stop;
1135         if (!hsock) return shareval(val_zero);
1136         stop = sock = (fsock ? fsock : hsock);
1137         do {
1138 	    sock = (num > 0) ?
1139 		(sock->next ? sock->next : hsock) :
1140 		(sock->prev ? sock->prev : tsock);
1141 	    num += (num<0) ? 1 : -1;
1142         } while (num && sock != stop);
1143         return newint(fg_sock(sock, quiet));
1144     }
1145 
1146     sock = (!(args->len - offset)) ? hsock : find_sock(args->data + offset);
1147     if (!sock) {
1148         if (!noerr) eprintf("no socket named '%s'", args->data + offset);
1149         return shareval(val_zero);
1150     }
1151     return newint(fg_sock(sock, quiet));
1152 }
1153 
1154 /* openworld
1155  * If (name && port), they are used as hostname and port number.
1156  * If (!port), name is used as the name of a world.  A NULL or empty name
1157  * corresponds to the first defined world.  A NULL name should be used for
1158  * the initial automatic connection, an empty name should be used for any
1159  * other unspecified connection.
1160  */
openworld(const char * name,const char * port,int flags)1161 int openworld(const char *name, const char *port, int flags)
1162 {
1163     World *world = NULL;
1164 
1165     if (!(flags & (CONN_FG | CONN_BG)))
1166 	flags |= (xsock == fsock) ? CONN_FG : CONN_BG;
1167     xsock = NULL;
1168     if (!port) {
1169         world = find_world(name);
1170         if (!world) {
1171             if (name) {
1172 		/* not H_CONFAIL (it needs a Sock, we haven't made one yet) */
1173                 eprintf("%s: %s",
1174                     *name ? name : "default world", "no such world");
1175             } else {
1176                 world_hook("---- No world ----", NULL);
1177 	    }
1178 	}
1179     } else {
1180         if (restriction >= RESTRICT_WORLD)
1181             eprintf("arbitrary connections restricted");
1182         else {
1183             world = new_world(NULL, "", name, port, "", "", "",
1184 		WORLD_TEMP | ((flags & CONN_SSL) ? WORLD_SSL : 0), "");
1185         }
1186     }
1187 
1188     return world ? opensock(world, flags) : 0;
1189 }
1190 
opensock(World * world,int flags)1191 static int opensock(World *world, int flags)
1192 {
1193     int gai_err;
1194     const char *what;
1195 
1196     if (world->sock) {
1197         if (world->sock->constate < SS_ZOMBIE) {
1198             eprintf("socket to %s already exists", world->name);
1199             return 0;
1200         }
1201         /* recycle existing Sock */
1202 	if (world->sock->constate == SS_DEAD)
1203 	    dead_socks--;
1204         xsock = world->sock;
1205 #if HAVE_SSL
1206 	if (xsock->ssl) {
1207 	    SSL_free(xsock->ssl); /* killsock() closed it, but didn't free it */
1208 	    xsock->ssl = NULL;
1209 	}
1210 #endif
1211 
1212     } else {
1213         /* create and initialize new Sock */
1214         if (!(xsock = world->sock = (Sock *) MALLOC(sizeof(struct Sock)))) {
1215             eprintf("opensock: not enough memory");
1216             return 0;
1217         }
1218         if (!world->screen)
1219             world->screen = new_screen(hist_getsize(world->history));
1220         xsock->world = world;
1221         xsock->prev = tsock;
1222         tsock = *(tsock ? &tsock->next : &hsock) = xsock;
1223         xsock->prompt = NULL;
1224 	xsock->prompt_timeout = tvzero;
1225         xsock->next = NULL;
1226 	xsock->myhost = NULL;
1227 	xsock->myaddr = NULL;
1228 	xsock->addrs = NULL;
1229 	xsock->addr = NULL;
1230 #if HAVE_SSL
1231 	xsock->ssl = NULL;
1232 #endif
1233     }
1234     Stringninit(xsock->buffer, 80);  /* data must be allocated */
1235     Stringninit(xsock->subbuffer, 1);
1236     init_queue(&xsock->queue);
1237     xsock->host = NULL;
1238     xsock->port = NULL;
1239     xsock->ttype = -1;
1240     xsock->fd = -1;
1241     xsock->pid = -1;
1242     xsock->fsastate = '\0';
1243     xsock->substate = '\0';
1244     xsock->attrs = 0;
1245     xsock->prepromptattrs = 0;
1246     xsock->alert_id = 0;
1247 #if HAVE_MCCP
1248     xsock->zstream = NULL;
1249 #endif
1250     VEC_ZERO(&xsock->tn_them);
1251     VEC_ZERO(&xsock->tn_them_tog);
1252     VEC_ZERO(&xsock->tn_us);
1253     VEC_ZERO(&xsock->tn_us_tog);
1254     xsock->constate = SS_NEW;
1255     xsock->flags = 0;
1256     gettime(&xsock->time[SOCK_SEND]);
1257     xsock->time[SOCK_RECV] = xsock->time[SOCK_SEND];
1258 
1259     if ((flags & CONN_QUIETLOGIN) && (flags & CONN_AUTOLOGIN) &&
1260 	world_character(world))
1261     {
1262 	xsock->numquiet = MAXQUIET;
1263     } else {
1264 	xsock->numquiet = 0;
1265     }
1266 
1267     if (flags & CONN_FG)
1268 	fg_sock(xsock, FALSE); /* XXX 2nd arg??? */
1269 
1270     if (flags & CONN_AUTOLOGIN) xsock->flags |= SOCKLOGIN;
1271     if (world->flags & WORLD_ECHO) xsock->flags |= SOCKECHO;
1272     if ((flags & CONN_SSL) || (world->flags & WORLD_SSL)) {
1273 #if HAVE_SSL
1274 	xsock->ssl = SSL_new(ssl_ctx);
1275 #else
1276         CONFAIL(xsock, "ssl", "not supported");
1277 #endif
1278     }
1279 
1280     if (!world->host) {
1281 	/* opening a connectionless socket */
1282         xsock->constate = SS_OPEN;
1283         return establish(xsock);
1284     } else if (!(world->flags & WORLD_NOPROXY) && proxy_host && *proxy_host) {
1285 	/* open a connection through a proxy */
1286         xsock->flags |= SOCKPROXY;
1287         xsock->host = STRDUP(proxy_host);
1288         xsock->port = (proxy_port && *proxy_port) ? proxy_port : "23";
1289         xsock->port = STRDUP(xsock->port);
1290     } else {
1291 	/* open a connection directly */
1292         xsock->host = STRDUP(world->host);
1293         xsock->port = STRDUP(world->port);
1294     }
1295 
1296     xsock->flags |= SOCKMAYTELNET;
1297 
1298     if (world->myhost && *world->myhost)
1299 	xsock->myhost = STRDUP(world->myhost);
1300     else if (tfhost)
1301 	xsock->myhost = STRDUP(tfhost);
1302     else
1303 	xsock->myhost = NULL;
1304 
1305     if (xsock->myhost) {
1306 	/* We don't bother with nonblocking:  this feature is rarely used,
1307 	 * and the address should be numeric or resolvable locally (quickly)
1308 	 * anyway, so it's not worth the complications of nonblocking. */
1309 	struct addrinfo hints;
1310 	int err;
1311 	memset(&hints, 0, sizeof(hints));
1312 	hints.ai_family = PF_UNSPEC;
1313 	hints.ai_socktype = SOCK_STREAM;
1314 	err = getaddrinfo(xsock->myhost, NULL, &hints, &xsock->myaddr);
1315 
1316 	if (err) {
1317 	    CONFAIL(xsock, xsock->myhost, gai_strerror(err));
1318 	    killsock(xsock);  /* can't nukesock(), this Sock may be recycled. */
1319 	    return 0;
1320 	}
1321     }
1322 
1323     xsock->constate = SS_RESOLVING;
1324     xsock->fd = get_host_address(xsock, &what, &gai_err);
1325     if (xsock->fd == 0) {
1326         /* The name lookup succeeded */
1327         xsock->constate = SS_RESOLVED;
1328 	xsock->addr = xsock->addrs;
1329         return openconn(xsock);
1330 #ifdef NONBLOCKING_GETHOST
1331     } else if (xsock->fd > 0) {
1332         /* The name lookup is pending.  We wait for it for a fraction of a
1333          * second here so "relatively fast" looks "immediate" to the user.
1334          */
1335         fd_set readable;
1336         struct timeval tv;
1337         FD_ZERO(&readable);
1338         FD_SET(xsock->fd, &readable);
1339         tv.tv_sec = 0;
1340         tv.tv_usec = CONN_WAIT;
1341         if (select(xsock->fd + 1, &readable, NULL, NULL, &tv) > 0) {
1342             /* The lookup completed. */
1343             return openconn(xsock);
1344         }
1345         /* select() returned 0, or -1 and errno==EINTR.  Either way, the
1346          * lookup needs more time.  So we add the fd to the set being
1347          * watched by main_loop(), and don't block here any longer.
1348          */
1349         readers_set(xsock->fd);
1350         do_hook(H_PENDING, "%% Hostname lookup for %s in progress.", "%s",
1351             xsock->world->name);
1352         return 2;
1353 #endif /* NONBLOCKING_GETHOST */
1354     } else {
1355         /* The name lookup failed */
1356         /* Note, some compilers can't handle (herr ? hsterror() : literal) */
1357         if (what)
1358             CONFAIL(xsock, what, strerror(errno));
1359         else if (gai_err)
1360             CONFAILHP(xsock, gai_strerror(gai_err));
1361         else
1362             CONFAILHP(xsock, "name lookup failed");
1363         killsock(xsock);  /* can't nukesock(), this may be a recycled Sock. */
1364         return 0;
1365     }
1366 }
1367 
1368 
printai(struct addrinfo * ai,const char * fmt_hp)1369 static const char *printai(struct addrinfo *ai, const char *fmt_hp)
1370 {
1371     static char buf[1024];
1372     static char hostbuf[INET6_ADDRSTRLEN+1];
1373     const void *hostaddr = NULL;
1374     unsigned short port = 0;
1375     const char *host = NULL;
1376 
1377     if (!fmt_hp) fmt_hp = "%s %d";
1378 
1379     switch (ai->ai_family) {
1380 	case AF_INET:
1381 	    hostaddr = &((struct sockaddr_in*)ai->ai_addr)->sin_addr;
1382 	    port = ((struct sockaddr_in*)ai->ai_addr)->sin_port;
1383 	    host = inet_ntoa(*(struct in_addr*)hostaddr);
1384 	    break;
1385 #if ENABLE_INET6
1386 	case AF_INET6:
1387 	    hostaddr = &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr;
1388 	    port = ((struct sockaddr_in6*)ai->ai_addr)->sin6_port;
1389 	    host = inet_ntop(ai->ai_family, hostaddr, hostbuf, sizeof(hostbuf));
1390 	    break;
1391 #endif
1392     }
1393     sprintf(buf, port ? fmt_hp : "%s", host ? host : "?", ntohs(port));
1394     return buf;
1395 }
1396 
ai_connect(int s,struct addrinfo * ai)1397 static inline int ai_connect(int s, struct addrinfo *ai)
1398 {
1399     do_hook(H_PENDING, "%% Trying to connect to %s: %s.", "%s %s",
1400 	xsock->world->name, printai(ai, NULL));
1401     return connect(s, ai->ai_addr, ai->ai_addrlen);
1402 }
1403 
setupnextconn(Sock * sock)1404 static void setupnextconn(Sock *sock)
1405 {
1406     struct addrinfo *ai, *next = sock->addr;
1407 
1408     if (sock->fd >= 0)
1409 	close(sock->fd);
1410 retry:
1411     next = next->ai_next;
1412     /* if next address is a duplicate of one we've already done, skip it */
1413     for (ai = sock->addrs; next && ai != next; ai = ai->ai_next) {
1414 	if (memcmp(ai->ai_addr, next->ai_addr, ai->ai_addrlen) == 0) {
1415 	    goto retry;
1416 	}
1417     }
1418     sock->addr = next;
1419 }
1420 
1421 /* If there are more addresses to try, hook ICONFAIL and try the next;
1422  * otherwise, hook CONFAIL and give up. */
ICONFAIL(Sock * sock,const char * what,const char * why)1423 static int ICONFAIL(Sock *sock, const char *what, const char *why)
1424 {
1425     setupnextconn(sock);
1426 
1427     if (sock->addr) {
1428 	do_hook(H_ICONFAIL, ICONFAIL_fmt, "%s %s: %s",
1429 	    (sock)->world->name, (what), (why));
1430 	oflush();
1431 	return openconn(sock);
1432     }
1433     do_hook(H_CONFAIL, "%% Connection to %s failed: %s: %s", "%s %s: %s",
1434 	(sock)->world->name, (what), (why));
1435     oflush();
1436     killsock(sock);
1437     return 0;
1438 }
1439 
openconn(Sock * sock)1440 static int openconn(Sock *sock)
1441 {
1442     int flags;
1443 
1444     xsock = sock;
1445 #ifdef NONBLOCKING_GETHOST
1446     if (xsock->constate == SS_RESOLVING) {
1447 	nbgai_hdr_t info = { 0, 0 };
1448 	struct addrinfo *ai;
1449         FD_CLR(xsock->fd, &readers);
1450         if (read(xsock->fd, &info, sizeof(info)) < 0 || info.err != 0) {
1451             if (!info.err)
1452                 CONFAIL(xsock, "read", strerror(errno));
1453             else
1454 		CONFAILHP(xsock, gai_strerror(info.err));
1455             close(xsock->fd);
1456             xsock->fd = -1;
1457 # ifdef PLATFORM_UNIX
1458 	    if (xsock->pid >= 0)
1459 		if (waitpid(xsock->pid, NULL, 0) < 0)
1460 		    tfprintf(tferr, "waitpid %ld: %s", xsock->pid, strerror(errno));
1461 	    xsock->pid = -1;
1462 # endif /* PLATFORM_UNIX */
1463             killsock(xsock);
1464             return 0;
1465         }
1466 	if (info.size <= 0) { /* shouldn't happen */
1467 	    xsock->addrs = NULL;
1468 	} else {
1469 	    xsock->addrs = XMALLOC(info.size);
1470 	    read(xsock->fd, (char*)xsock->addrs, info.size);
1471 	}
1472         close(xsock->fd);
1473 # ifdef PLATFORM_UNIX
1474         if (xsock->pid >= 0)
1475             if (waitpid(xsock->pid, NULL, 0) < 0)
1476                tfprintf(tferr, "waitpid: %ld: %s", xsock->pid, strerror(errno));
1477         xsock->pid = -1;
1478 # endif /* PLATFORM_UNIX */
1479         xsock->constate = SS_RESOLVED;
1480 	for (ai = xsock->addrs; ai; ai = ai->ai_next) {
1481 	    ai->ai_addr = (struct sockaddr*)((char*)ai + sizeof(*ai));
1482 	    if (ai->ai_next != 0) {
1483 		ai->ai_next =
1484 		    (struct addrinfo*)((char*)ai->ai_addr + ROUND_UP_LENGTH(ai->ai_addrlen));
1485 	    }
1486 	}
1487 	xsock->addr = xsock->addrs;
1488     }
1489 #endif /* NONBLOCKING_GETHOST */
1490 
1491 #if 0
1492     /* Jump back here if we start a nonblocking connect and then discover
1493      * that the platform has a broken read() or select().
1494      */
1495     retry:
1496 #endif
1497 
1498     if (!xsock->addr) {
1499 	CONFAILHP(xsock, "no usable addresses");
1500 	killsock(xsock);
1501 	return 0;
1502     }
1503 
1504     xsock->fd = socket(xsock->addr->ai_family, xsock->addr->ai_socktype,
1505 	xsock->addr->ai_protocol);
1506     if (xsock->fd < 0) {
1507 	if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)
1508 	    return ICONFAIL(xsock, "socket", strerror(errno));
1509         CONFAIL(xsock, "socket", strerror(errno));
1510         killsock(xsock);
1511         return 0;
1512     }
1513 
1514     if (xsock->myaddr && bind(xsock->fd, xsock->myaddr->ai_addr,
1515 	xsock->myaddr->ai_addrlen) < 0)
1516     {
1517         CONFAIL(xsock, printai(xsock->myaddr, NULL), strerror(errno));
1518         killsock(xsock);
1519         return 0;
1520     }
1521 
1522 #if HAVE_SSL
1523     if (xsock->ssl && SSL_set_fd(xsock->ssl, xsock->fd) <= 0) {
1524         CONFAIL(xsock, "SSL", ERR_error_string(ERR_get_error(), NULL));
1525         killsock(xsock);
1526         return 0;
1527     }
1528 #endif
1529 
1530     if (xsock->fd >= nfds) nfds = xsock->fd + 1;
1531 
1532     if (!TF_NONBLOCK) {
1533         set_var_by_id(VAR_async_conn, 0);
1534     } else if (async_conn) {
1535         /* note: 3rd arg to fcntl() is optional on Unix, but required by OS/2 */
1536         if ((flags = fcntl(xsock->fd, F_GETFL, 0)) < 0) {
1537             operror("Can't make socket nonblocking: F_GETFL fcntl");
1538             set_var_by_id(VAR_async_conn, 0);
1539         } else if ((fcntl(xsock->fd, F_SETFL, flags | TF_NONBLOCK)) < 0) {
1540             operror("Can't make socket nonblocking: F_SETFL fcntl");
1541             set_var_by_id(VAR_async_conn, 0);
1542         }
1543     }
1544 
1545     if (keepalive) {
1546 	flags = 1;
1547 	if (setsockopt(xsock->fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&flags,
1548 	    sizeof(flags)) < 0)
1549 	{
1550 	    wprintf("setsockopt KEEPALIVE: %s", strerror(errno));
1551 	}
1552     }
1553 
1554     xsock->constate = SS_CONNECTING;
1555     if (ai_connect(xsock->fd, xsock->addr) == 0) {
1556         /* The connection completed successfully. */
1557         xsock->constate = SS_CONNECTED;
1558         return establish(xsock);
1559 
1560 #ifdef EINPROGRESS
1561     } else if (errno == EINPROGRESS) {
1562         /* The connection needs more time.  It will select() as writable when
1563          * it has connected, or readable when it has failed.  We select() it
1564          * briefly here so "fast" looks synchronous to the user.
1565          */
1566         fd_set writeable;
1567         struct timeval tv;
1568         FD_ZERO(&writeable);
1569         FD_SET(xsock->fd, &writeable);
1570         tv.tv_sec = 0;
1571         tv.tv_usec = CONN_WAIT;
1572         if (select(xsock->fd + 1, NULL, &writeable, NULL, &tv) > 0) {
1573             /* The connection completed. */
1574             return establish(xsock);
1575         }
1576         /* select() returned 0, or -1 and errno==EINTR.  Either way, the
1577          * connection needs more time.  So we add the fd to the set being
1578          * watched by main_loop(), and don't block here any longer.
1579          */
1580         FD_SET(xsock->fd, &writers);
1581         FD_SET(xsock->fd, &readers);
1582         return 2;
1583 #endif /* EINPROGRESS */
1584 
1585 #if 0  /* this can cause problems on nonbuggy systems, so screw the sysv bug */
1586     } else if (can_nonblock && (errno == EAGAIN
1587 # ifdef EWOULDBLOCK
1588                                                 || errno == EWOULDBLOCK
1589 # endif
1590                                                                        )) {
1591         /* A bug in SVR4.2 causes nonblocking connect() to (sometimes?)
1592          * incorrectly fail with EAGAIN.  The only thing we can do about
1593          * it is to try a blocking connect().
1594          */
1595         close(xsock->fd);
1596         can_nonblock = FALSE;
1597         goto retry; /* try again */
1598 #endif /* 0 */
1599     }
1600 
1601     /* The connection failed; try the next address. */
1602     return ICONFAIL_AI(xsock, strerror(errno));
1603 }
1604 
1605 #if !HAVE_GETADDRINFO
1606 /* Partial implementation of getaddrinfo():  returns a single address for an
1607  * IPv6 address OR IPv4 address OR a name that resolves to an IPv4 address.
1608  * Ignores hints except for AI_NUMERICHOST.  Port is optional.
1609  */
tfgetaddrinfo(const char * nodename,const char * port,const struct addrinfo * hints,struct addrinfo ** res)1610 static int tfgetaddrinfo(const char *nodename, const char *port,
1611     const struct addrinfo *hints, struct addrinfo **res)
1612 {
1613     struct servent *service;
1614     struct hostent *host;
1615     unsigned short portnum = 0, sa_len = 0;
1616     int err = 0;
1617     struct {
1618 	struct addrinfo ai;
1619 	union {
1620 	    struct sockaddr sa;
1621 	    struct sockaddr_in sin4;
1622 # if ENABLE_INET6
1623 	    struct sockaddr_in6 sin6;
1624 # endif
1625 	} sa;
1626     } *blob;
1627 
1628     blob = MALLOC(sizeof(*blob));
1629     if (!blob) return TF_EAI_MEMORY;
1630 
1631     /* translate/look up port */
1632     if (port) {
1633 	if (is_digit(*port)) {
1634 	    portnum = htons(atoi(port));
1635 # ifdef NETDB_H
1636 	} else if ((service = getservbyname(port, "tcp"))) {
1637 	    portnum = service->s_port;
1638 # endif
1639 	} else {
1640 	    err = TF_EAI_SERVICE;
1641 	    goto error;
1642 	}
1643     }
1644 
1645 # if ENABLE_INET6
1646     /* translate numeric IPv6 address */
1647     if (inet_pton(AF_INET6, nodename, &blob->sa.sin6.sin6_addr)) {
1648 	sa_len = sizeof(blob->sa.sin6);
1649 	blob->sa.sa.sa_family = PF_INET6;
1650 	blob->sa.sin6.sin6_port = portnum;
1651 	goto found;
1652     }
1653 # endif
1654 
1655     /* translate numeric IPv4 address */
1656 # if HAVE_INET_ATON
1657     if (inet_aton(nodename, &blob->sa.sin4.sin_addr))
1658 # elif !defined(dgux)
1659     /* Most versions of inet_addr() return a long. */
1660     blob->sa.sin4.sin_addr.s_addr = inet_addr(nodename);
1661     if (blob->sa.sin4.sin_addr.s_addr != INADDR_NONE)
1662 # else
1663     /* DGUX's inet_addr() returns a struct in_addr. */
1664     blob->sa.sin4.sin_addr.s_addr = inet_addr(nodename).s_addr;
1665     if (blob->sa.sin4.sin_addr.s_addr != INADDR_NONE)
1666 # endif /* HAVE_INET_ATON */
1667     {
1668 	sa_len = sizeof(blob->sa.sin4);
1669 	blob->sa.sa.sa_family = PF_INET;
1670 	blob->sa.sin4.sin_port = portnum;
1671         goto found;
1672     }
1673 
1674     if (hints->ai_flags & AI_NUMERICHOST) {
1675 	FREE(blob);
1676 	*res = NULL;
1677 	return TF_EAI_NODATA;
1678     }
1679 
1680     /* look up text address (IPv4 only) */
1681     host = gethostbyname(nodename);
1682     if (!host) {
1683 	err = h_errno;
1684 	goto error;
1685     }
1686     sa_len = sizeof(blob->sa.sin4);
1687     blob->sa.sa.sa_family = PF_INET;
1688     blob->sa.sin4.sin_port = portnum;
1689     memcpy((void *)&blob->sa.sin4.sin_addr, (void *)host->h_addr,
1690 	sizeof(blob->sa.sin4.sin_addr));
1691 
1692 found:
1693 # if HAVE_SOCKADDR_SA_LEN
1694     blob->sa.sa.sa_len = sa_len;
1695 # endif
1696     blob->ai.ai_family = blob->sa.sa.sa_family;
1697     blob->ai.ai_socktype = SOCK_STREAM;
1698     blob->ai.ai_protocol = IPPROTO_TCP;
1699     blob->ai.ai_addrlen = sa_len;
1700     blob->ai.ai_canonname = NULL;
1701     blob->ai.ai_addr = (struct sockaddr*)&blob->sa;
1702     blob->ai.ai_next = NULL;
1703     *res = &blob->ai;
1704     return 0;
1705 
1706 error:
1707     FREE(blob);
1708     return err;
1709 }
1710 #endif /* !HAVE_GETADDRINFO */
1711 
tffreeaddrinfo(struct addrinfo * ai)1712 static void tffreeaddrinfo(struct addrinfo *ai)
1713 {
1714     /* ai and all contents were allocated in single chunk by tfgetaddrinfo()
1715      * or completed nonblocking resolution in openconn() */
1716     FREE(ai);
1717 }
1718 
1719 /* Convert name or ip number string to a list of struct addrinfo.
1720  * Returns -1 for failure, 0 for success, or a positive file descriptor
1721  * connected to a pending name lookup process or thread.
1722  */
get_host_address(Sock * sock,const char ** what,int * errp)1723 static int get_host_address(Sock *sock, const char **what, int *errp)
1724 {
1725     struct addrinfo hints;
1726     memset(&hints, 0, sizeof(hints));
1727     hints.ai_family = PF_UNSPEC;
1728     hints.ai_socktype = SOCK_STREAM;
1729     hints.ai_flags = AI_NUMERICHOST;
1730 #if 0 /* AI_ADDRCONFIG is defined on FreeBSD 4.2, but causes an error in
1731 	 getaddrinfo() (this was fixed by 4.8).  It's not important to
1732 	 use the flag, so it's easier to not use it and avoid the problem. */
1733 # ifdef AI_ADDRCONFIG
1734     hints.ai_flags |= AI_ADDRCONFIG;
1735 # endif
1736 #endif
1737     *errp = getaddrinfo(sock->host, sock->port, &hints, &sock->addrs);
1738     *what = NULL;
1739     if (*errp == 0) return 0;
1740 
1741 #ifdef NONBLOCKING_GETHOST
1742     if (async_name) {
1743 	/* do nonblocking for non-numeric */
1744 	*errp = 0;
1745 	*what = NULL;
1746 	sock->flags |= SOCKALLOCADDRS;
1747 	return nonblocking_gethost(sock->host, sock->port, &sock->addrs,
1748 	    &sock->pid, what);
1749     } else
1750 #endif
1751     {
1752 	hints.ai_flags &= ~AI_NUMERICHOST;
1753 	*errp = getaddrinfo(sock->host, sock->port, &hints, &sock->addrs);
1754 	*what = NULL;
1755 	if (*errp == 0) return 0;
1756     }
1757     return -1;
1758 }
1759 
1760 #ifdef NETDB_H
1761 #ifdef NONBLOCKING_GETHOST
1762 
waitforhostname(int fd,const char * name,const char * port)1763 static void waitforhostname(int fd, const char *name, const char *port)
1764 {
1765     /* Uses writev() so the write is atomic, to avoid race condition between
1766      * writer and reader processes.  (Really, the reader should loop reading
1767      * until EOF.)
1768      */
1769     struct addrinfo *res, *ai;
1770     struct addrinfo hints;
1771     nbgai_hdr_t hdr;
1772 #define NIOV 1+2*16
1773     struct iovec iov[NIOV];
1774     int niov;
1775 
1776     memset(&hints, 0, sizeof(hints));
1777     hints.ai_family = PF_UNSPEC;
1778     hints.ai_socktype = SOCK_STREAM;
1779 
1780     hdr.err = getaddrinfo(name, port, &hints, &res);
1781 
1782     if (!hdr.err) {
1783 	hdr.size = 0;
1784 	iov[0].iov_base = (char*)&hdr;
1785 	iov[0].iov_len = sizeof(hdr);
1786 	niov = 1;
1787 	for (ai = res; ai && niov < NIOV; ai = ai->ai_next) {
1788 	    static const char zeros[ 8 ] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1789 	    size_t padded = ROUND_UP_LENGTH(ai->ai_addrlen);
1790 	    hdr.size += sizeof(*ai) + padded;
1791 	    iov[niov].iov_base = (char*)ai;
1792 	    iov[niov].iov_len = sizeof(*ai);
1793 	    niov++;
1794 	    iov[niov].iov_base = (char*)ai->ai_addr;
1795 	    iov[niov].iov_len = ai->ai_addrlen;
1796 	    niov++;
1797 	    if (padded != ai->ai_addrlen) {
1798 		/* padding */
1799 		iov[niov].iov_base = (char*)zeros;
1800 		iov[niov].iov_len = padded - ai->ai_addrlen;
1801 		niov++;
1802 	    }
1803 	}
1804 	writev(fd, iov, niov);
1805 	if (res) freeaddrinfo(res);
1806     } else {
1807 	hdr.size = 0;
1808 	write(fd, &hdr, sizeof(hdr));
1809     }
1810     close(fd);
1811 }
1812 
1813 # ifdef PLATFORM_OS2
1814 typedef struct _threadpara {
1815     const char *hostname;
1816     const char *port;
1817     int   fd;
1818 } threadpara;
1819 
os2waitforhostname(threadpara * targs)1820 void os2waitforhostname(threadpara *targs)
1821 {
1822     waitforhostname(targs->fd, targs->hostname, targs->port);
1823     FREE(targs->hostname);
1824     FREE(targs->port);
1825     FREE(targs);
1826 }
1827 # endif /* PLATFORM_OS2 */
1828 
nonblocking_gethost(const char * name,const char * port,struct addrinfo ** res,pid_t * pidp,const char ** what)1829 static int nonblocking_gethost(const char *name, const char *port,
1830     struct addrinfo **res, pid_t *pidp, const char **what)
1831 {
1832     int fds[2];
1833     int err;
1834 
1835     *what = "pipe";
1836     if (pipe(fds) < 0) return -1;
1837 
1838 #ifdef PLATFORM_UNIX
1839     {
1840         *what = "fork";
1841         *pidp = fork();
1842         if (*pidp > 0) {          /* parent */
1843             close(fds[1]);
1844             return fds[0];
1845         } else if (*pidp == 0) {  /* child */
1846             close(fds[0]);
1847             waitforhostname(fds[1], name, port);
1848             exit(0);
1849         }
1850     }
1851 #endif
1852 #ifdef PLATFORM_OS2
1853     {
1854         threadpara *tpara;
1855 
1856         if ((tpara = XMALLOC(sizeof(threadpara)))) {
1857             setmode(fds[0],O_BINARY);
1858             setmode(fds[1],O_BINARY);
1859             tpara->fd = fds[1];
1860             tpara->hostname = STRDUP(name);
1861             tpara->port = STRDUP(port);
1862 
1863             /* BUG: gethostbyname() isn't threadsafe! */
1864             *what = "_beginthread";
1865             if (_beginthread(os2waitforhostname,NULL,0x8000,(void*)tpara) != -1)
1866                 return(fds[0]);
1867         }
1868     }
1869 #endif
1870 
1871     /* failed */
1872     err = errno;
1873     close(fds[0]);
1874     close(fds[1]);
1875     errno = err;
1876     return -1;
1877 }
1878 #endif /* NONBLOCKING_GETHOST */
1879 #endif /* NETDB_H */
1880 
1881 
1882 /* Establish a sock for which connect() has completed. */
establish(Sock * sock)1883 static int establish(Sock *sock)
1884 {
1885     xsock = sock;
1886 #if TF_NONBLOCK
1887     if (xsock->constate == SS_CONNECTING) {
1888         int err = 0, flags;
1889         socklen_t len = sizeof(err);
1890 
1891         /* Old Method 1: If read(fd, buf, 0) fails, the connect() failed, and
1892          * errno will explain why.  Problem: on some systems, a read() of
1893          * 0 bytes is always successful, even if socket is not connected.
1894          */
1895         /* Old Method 2: If a second connect() fails with EISCONN, the first
1896          * connect() worked.  On the slim chance that the first failed, but
1897          * the second worked, use that.  Otherwise, use getsockopt(SO_ERROR)
1898          * to find out why the first failed.  If SO_ERROR isn't available,
1899          * use read() to get errno.  This method works for all systems, as
1900          * well as SOCKS 4.2beta.  Problems: Some socket implementations
1901          * give the wrong errno; extra net traffic on failure.
1902          */
1903         /* CURRENT METHOD:  If possible, use getsockopt(SO_ERROR) to test for
1904          * an error.  This avoids the overhead of a second connect(), and the
1905          * possibility of getting the error value from the second connect()
1906          * (linux).  (Potential problem: it's possible that some systems
1907          * don't clear the SO_ERROR value for successful connect().)
1908          * If SO_ERROR is not available or we are using SOCKS, we try to read
1909          * 0 bytes.  If it fails, the connect() must have failed.  If it
1910          * succeeds, we can't know if it's because the connection really
1911          * succeeded, or the read() did a no-op for the 0 size, so we try a
1912          * second connect().  If the second connect() fails with EISCONN, the
1913          * first connect() worked.  If it works (unlikely), use it.  Otherwise,
1914          * use read() to get the errno.
1915          * Tested on:  Linux, HP-UX, Solaris, Solaris with SOCKS5...
1916          */
1917         /* Alternative: replace second connect() with getpeername(), and
1918          * check for ENOTCONN.  Disadvantage: doesn't work with SOCKS, etc.
1919          */
1920 
1921 #ifdef SO_ERROR
1922 # if !SOCKS
1923 #  define USE_SO_ERROR
1924 # endif
1925 #endif
1926 
1927 #ifdef USE_SO_ERROR
1928         if (getsockopt(xsock->fd, SOL_SOCKET, SO_ERROR, (void*)&err, &len) < 0)
1929         {
1930             return ICONFAIL(xsock, "getsockopt", strerror(errno));
1931         }
1932 
1933 #else
1934         {
1935             char ch;
1936             if (read(xsock->fd, &ch, 0) < 0) {
1937 		return ICONFAIL(xsock, "nonblocking connect/read", strerror(errno));
1938             } else if ((ai_connect(xsock->fd, xsock->addr) < 0) &&
1939                 errno != EISCONN)
1940             {
1941                 read(xsock->fd, &ch, 1);   /* must fail */
1942 		return ICONFAIL(xsock, "nonblocking connect 2/read", strerror(errno));
1943             }
1944         }
1945 #endif
1946         if (err != 0) {
1947 	    return ICONFAIL_AI(xsock, strerror(err));
1948         }
1949 
1950         /* connect() worked.  Clear the pending stuff, and get on with it. */
1951         xsock->constate = SS_CONNECTED;
1952         FD_CLR(xsock->fd, &writers);
1953 
1954         /* Turn off nonblocking (this should help on buggy systems). */
1955         /* note: 3rd arg to fcntl() is optional on Unix, but required by OS/2 */
1956         if ((flags = fcntl(xsock->fd, F_GETFL, 0)) >= 0)
1957             fcntl(xsock->fd, F_SETFL, flags & ~TF_NONBLOCK);
1958     }
1959 #endif /* TF_NONBLOCK */
1960 
1961     if (xsock->constate == SS_CONNECTED)
1962 	FD_SET(xsock->fd, &readers);
1963 
1964     /* hack: sockaddr_in.sin_port and sockaddr_in6.sin6_port coincide */
1965     if (xsock->addr &&
1966 	ntohs(((struct sockaddr_in*)xsock->addr->ai_addr)->sin_port) == 23)
1967 	    xsock->flags |= SOCKTELNET;
1968 
1969 #if HAVE_SSL
1970     if (xsock->ssl) {
1971 	int sslret;
1972 	sslret = SSL_connect(xsock->ssl);
1973 	if (sslret <= 0) {
1974 	    setupnextconn(xsock);
1975 	    ssl_io_err(xsock, sslret, xsock->addr ? H_ICONFAIL : H_CONFAIL);
1976 	    if (xsock->addr)
1977 		return openconn(xsock);
1978 	    killsock(xsock);
1979 	    return 0;
1980 	}
1981     }
1982 #endif
1983 
1984     /* atomicness ends here */
1985 
1986     if (xsock == fsock)   /* possible for a recycled zombie */
1987         update_status_field(NULL, STAT_WORLD);
1988 
1989     if (xsock->flags & SOCKTELNET)
1990         preferred_telnet_options();
1991 
1992     if (sock->flags & SOCKPROXY) {
1993         FREE(sock->host);
1994         FREE(sock->port);
1995         sock->host = STRDUP(sock->world->host);
1996         sock->port = STRDUP(sock->world->port);
1997         do_hook(H_PROXY, "", "%s", sock->world->name);
1998     }
1999 
2000     wload(sock->world);
2001 
2002     if (!(sock->flags & SOCKPROXY)) {
2003 #if HAVE_SSL
2004 	if (sock->ssl)
2005 	    do_hook(H_CONNECT, "%% Connected to %s using cipher %s.", "%s %s",
2006 		sock->world->name, SSL_get_cipher_name(sock->ssl));
2007 	else
2008 #endif
2009 	    do_hook(H_CONNECT, "%% Connected to %s.", "%s", sock->world->name);
2010 
2011         if (login && sock->flags & SOCKLOGIN) {
2012             if (world_character(sock->world) && world_pass(sock->world))
2013                 do_hook(H_LOGIN, NULL, "%s %s %s", sock->world->name,
2014                     world_character(sock->world), world_pass(sock->world));
2015             sock->flags &= ~SOCKLOGIN;
2016         }
2017     }
2018 
2019     return 1;
2020 }
2021 
2022 /* clear most of sock's fields, but leave it consistent and extant */
killsock(Sock * sock)2023 static void killsock(Sock *sock)
2024 {
2025     if (sock->constate >= SS_ZOMBIE) return;
2026 #if 0 /* There may be a disconnect hook AFTER this function... */
2027     if (sock == fsock || sock->queue.list.head || sock->world->screen->nnew) {
2028 	sock->constate = SS_ZOMBIE;
2029     } else {
2030 	sock->constate = SS_DEAD;
2031 	dead_socks++;
2032     }
2033 #else /* ... so we must unconditionally enter ZOMBIE state. */
2034     sock->constate = SS_ZOMBIE;
2035 #endif
2036     sock->fsastate = '\0';
2037     sock->attrs = 0;
2038     VEC_ZERO(&sock->tn_them);
2039     VEC_ZERO(&sock->tn_them_tog);
2040     VEC_ZERO(&sock->tn_us);
2041     VEC_ZERO(&sock->tn_us_tog);
2042     Stringfree(sock->buffer);
2043     Stringfree(sock->subbuffer);
2044 
2045     unprompt(sock, sock==fsock);
2046 
2047     if (sock->host) FREE(sock->host);
2048     if (sock->port) FREE(sock->port);
2049     if (sock->myhost) FREE(sock->myhost);
2050     sock->host = sock->port = sock->myhost = NULL;
2051 
2052     if (sock->addrs) {
2053 	if (sock->flags & SOCKALLOCADDRS)
2054 	    tffreeaddrinfo(sock->addrs);
2055 	else
2056 	    freeaddrinfo(sock->addrs);
2057 	sock->addrs = NULL;
2058     }
2059     if (sock->myaddr) {
2060 	freeaddrinfo(sock->myaddr);
2061 	sock->myaddr = NULL;
2062     }
2063 #if HAVE_SSL
2064     if (sock->ssl) {
2065 	SSL_shutdown(sock->ssl);
2066 	/* Don't SSL_free() yet: we still need to be able to use SSL_error() */
2067     }
2068 #endif
2069     if (sock->fd >= 0) {
2070         FD_CLR(sock->fd, &readers);
2071         FD_CLR(sock->fd, &writers);
2072         close(sock->fd);
2073         sock->fd = -1;
2074     }
2075 #if HAVE_MCCP
2076     if (sock->zstream) {
2077 	inflateEnd(sock->zstream);
2078 	FREE(sock->zstream);
2079     }
2080 #endif
2081 #ifdef NONBLOCKING_GETHOST
2082 # ifdef PLATFORM_UNIX
2083     if (sock->pid >= 0) {
2084         kill(sock->pid, SIGTERM);
2085         if (waitpid(sock->pid, NULL, 0) < 0)
2086             tfprintf(tferr, "waitpid: %ld: %s", sock->pid, strerror(errno));
2087         sock->pid = -1;
2088     }
2089 # endif /* PLATFORM_UNIX */
2090 #endif /* NONBLOCKING_GETHOST */
2091     if (sock == fsock)
2092 	update_status_field(NULL, STAT_WORLD);
2093 }
2094 
2095 /* nukesock
2096  * Remove socket from list and free memory.  Should only be called on a
2097  * Sock which is known to have no references other than the socket list.
2098  */
nukesock(Sock * sock)2099 static void nukesock(Sock *sock)
2100 {
2101     if (sock->queue.list.head) {
2102 	internal_error(__FILE__, __LINE__, "socket %s has unprocessed lines",
2103 	    !sock ? "!sock" :
2104 	    !sock->world ? "!sock->world" :
2105 	    sock->world->name);
2106 	socks_with_lines--;
2107     }
2108     if (sock == xsock) xsock = NULL;
2109     sock->world->sock = NULL;
2110     killsock(sock);
2111     *((sock == hsock) ? &hsock : &sock->prev->next) = sock->next;
2112     *((sock == tsock) ? &tsock : &sock->next->prev) = sock->prev;
2113     if (sock->world->screen->active) {
2114 	sock->world->screen->active = 0;
2115         --active_count;
2116         update_status_field(NULL, STAT_ACTIVE);
2117     }
2118     if (sock->world->flags & WORLD_TEMP) {
2119         nuke_world(sock->world);
2120         sock->world = NULL;
2121     }
2122 #if HAVE_SSL
2123     if (sock->ssl) {
2124 	SSL_free(sock->ssl);
2125 	sock->ssl = NULL;
2126     }
2127 #endif
2128     FREE(sock);
2129 }
2130 
2131 #if 0
2132 static void fg_live_sock(void)
2133 {
2134     /* If the fg sock is dead, find another sock to put in fg.  Since this
2135      * is called from main_loop(), xsock must be the same as fsock.  We must
2136      * keep it that way.  Note that a user hook in fg_sock() could kill the
2137      * new fg sock, so we must loop until the new fg sock stays alive.
2138      */
2139     while (fsock && (fsock->constate >= SS_ZOMBIE)) {
2140         for (xsock = hsock; xsock; xsock = xsock->next) {
2141             if (xsock->constate < SS_ZOMBIE)
2142 		break;
2143         }
2144         fg_sock(xsock, FALSE);
2145     }
2146 }
2147 #endif
2148 
2149 /* delete all dead sockets */
nuke_dead_socks(void)2150 static void nuke_dead_socks(void)
2151 {
2152     Sock *sock, *next;
2153 
2154     for (sock = hsock; sock; sock = next) {
2155         next = sock->next;
2156         if (sock->constate == SS_ZOMBIE) {
2157 	    if (sock->fd >= 0)
2158 		FD_CLR(sock->fd, &readers);
2159         } else if (sock->constate == SS_DEAD) {
2160             nukesock(sock);
2161             dead_socks--;
2162         }
2163     }
2164     if (quitdone && !hsock) quit_flag = 1;
2165 }
2166 
queue_socket_line(Sock * sock,const conString * line,int offset,attr_t attr)2167 static void queue_socket_line(Sock *sock, const conString *line, int offset,
2168     attr_t attr)
2169 {
2170     String *new;
2171     (new = StringnewM(NULL, line->len - offset, 0, sock->world->md))->links++;
2172     SStringocat(new, line, offset);
2173     new->attrs |= attr;
2174     gettime(&new->time);
2175     sock->time[SOCK_RECV] = new->time;
2176     new->attrs &= ~F_GAG; /* in case gagged line was passed via fake_recv() */
2177     if (!sock->queue.list.head)
2178 	socks_with_lines++;
2179     enqueue(&sock->queue, new);
2180 }
2181 
dc(Sock * s)2182 static void dc(Sock *s)
2183 {
2184     String *buffer = Stringnew(NULL, -1, 0);
2185     Sock *oldxsock = xsock;
2186     xsock = s;
2187     flushxsock();
2188     Sprintf(buffer, "%% Connection to %s closed.", s->world->name);
2189     world_output(s->world, CS(buffer));
2190     if (xsock != fsock) oputline(CS(buffer));
2191     zombiesock(xsock);
2192     xsock = oldxsock;
2193 }
2194 
2195 /* disconnect a socket */
handle_dc_command(String * args,int offset)2196 struct Value *handle_dc_command(String *args, int offset)
2197 {
2198     Sock *s;
2199 
2200     if (!(args->len - offset)) {
2201         if (!xsock) {
2202             eprintf("no current socket");
2203             return shareval(val_zero);
2204         }
2205 	dc(xsock);
2206     } else if (cstrcmp(args->data + offset, "-all") == 0) {
2207         for (s = hsock; s; s = s->next)
2208 	    if (s->constate < SS_DEAD)
2209 		dc(s);
2210     } else {
2211         if ((s = find_sock(args->data + offset)) && (s->constate < SS_DEAD)) {
2212 	    dc(s);
2213         } else {
2214             eprintf("Not connected to %s", args->data + offset);
2215             return shareval(val_zero);
2216         }
2217     }
2218     return shareval(val_one);
2219 }
2220 
socklinescmp(const void * a,const void * b)2221 static int socklinescmp(const void *a, const void *b) {
2222     return (*(Sock**)a)->world->screen->nnew -
2223 	   (*(Sock**)b)->world->screen->nnew;
2224 }
2225 
sockidlecmp(const void * a,const void * b)2226 static int sockidlecmp(const void *a, const void *b) {
2227     return tvcmp(&(*(Sock**)b)->time[SOCK_RECV],
2228 	         &(*(Sock**)a)->time[SOCK_RECV]);
2229 }
2230 
socknamecmp(const void * a,const void * b)2231 static int socknamecmp(const void *a, const void *b) {
2232     return nullcstrcmp((*(Sock**)a)->world->name, (*(Sock**)b)->world->name);
2233 }
2234 
socktypecmp(const void * a,const void * b)2235 static int socktypecmp(const void *a, const void *b) {
2236     return nullcstrcmp((*(Sock**)a)->world->type, (*(Sock**)b)->world->type);
2237 }
2238 
sockhostcmp(const void * a,const void * b)2239 static int sockhostcmp(const void *a, const void *b) {
2240     return nullcstrcmp((*(Sock**)a)->world->host, (*(Sock**)b)->world->host);
2241 }
2242 
sockportcmp(const void * a,const void * b)2243 static int sockportcmp(const void *a, const void *b) {
2244     return nullcstrcmp((*(Sock**)a)->world->port, (*(Sock**)b)->world->port);
2245 }
2246 
sockcharcmp(const void * a,const void * b)2247 static int sockcharcmp(const void *a, const void *b) {
2248     return nullcstrcmp((*(Sock**)a)->world->character,
2249 		       (*(Sock**)b)->world->character);
2250 }
2251 
2252 /* display list of open sockets and their state. */
handle_listsockets_command(String * args,int offset)2253 struct Value *handle_listsockets_command(String *args, int offset)
2254 {
2255     Sock *sock;
2256     Vector socks = vector_init(32);
2257     char idlebuf[16], linebuf[16], addrbuf[64], state;
2258     const char *ptr;
2259     time_t now;
2260     int t, n, opt, i, nnew, nold;
2261     int error = 0, shortflag = FALSE, mflag = matching, numeric = 0;
2262     Pattern pat_name, pat_type;
2263     int typewidth = 11, namewidth = 15, hostwidth = 26;
2264     int (*cmp)(const void *, const void *) = NULL;
2265 
2266     init_pattern_str(&pat_name, NULL);
2267     init_pattern_str(&pat_type, NULL);
2268 
2269     startopt(CS(args), "m:sT:nS:");
2270     while ((opt = nextopt(&ptr, NULL, NULL, &offset))) {
2271         switch(opt) {
2272         case 'm':
2273             if ((mflag = enum2int(ptr, 0, enum_match, "-m")) < 0)
2274                 goto listsocket_error;
2275             break;
2276         case 's':
2277             shortflag = TRUE;
2278             break;
2279         case 'T':
2280             free_pattern(&pat_type);
2281             error += !init_pattern_str(&pat_type, ptr);
2282             break;
2283 	case 'n':
2284 	    numeric = 1;
2285 	    break;
2286 	case 'S':
2287 	    n = strlen(ptr);
2288 	    if (n == 0 || cstrncmp(ptr, "name", n) == 0)
2289 		cmp = socknamecmp;
2290 	    else if (cstrncmp(ptr, "lines", n) == 0)
2291 		cmp = socklinescmp;
2292 	    else if (cstrncmp(ptr, "idle", n) == 0)
2293 		cmp = sockidlecmp;
2294 	    else if (cstrncmp(ptr, "type", n) == 0)
2295 		cmp = socktypecmp;
2296 	    else if (cstrncmp(ptr, "host", n) == 0)
2297 		cmp = sockhostcmp;
2298 	    else if (cstrncmp(ptr, "port", n) == 0)
2299 		cmp = sockportcmp;
2300 	    else if (cstrncmp(ptr, "character", n) == 0)
2301 		cmp = sockcharcmp;
2302 	    else if (cstrncmp(ptr, "-", n) == 0)
2303 		cmp = NULL;
2304 	    else { eprintf("invalid sort criterion"); error++; }
2305 	    break;
2306         default:
2307             goto listsocket_error;
2308         }
2309     }
2310     if (error) goto listsocket_error;
2311     init_pattern_mflag(&pat_type, mflag, 'T');
2312     Stringstriptrail(args);
2313     if (args->len > offset)
2314         error += !init_pattern(&pat_name, args->data + offset, mflag);
2315     if (error) goto listsocket_error;
2316 
2317     if (!hsock) {
2318         if (!shortflag) eprintf("Not connected to any sockets.");
2319         goto listsocket_error;
2320     }
2321 
2322     /* collect matching socks */
2323     for (sock = hsock; sock; sock = sock->next) {
2324         if (pat_type.str &&
2325             !patmatch(&pat_type, NULL,
2326 		sock->world->type ? sock->world->type : ""))
2327             continue;
2328         if (args->len - offset && !patmatch(&pat_name, NULL, sock->world->name))
2329             continue;
2330 	vector_add(&socks, sock);
2331     }
2332 
2333     if (cmp)
2334 	vector_sort(&socks, cmp);
2335 
2336     if (numeric) {
2337 	namewidth += 3;
2338 	typewidth += 3;
2339 	hostwidth = 20;
2340     }
2341 
2342     now = time(NULL);
2343 
2344     if (!shortflag)
2345         oprintf("    %8s %4s %-*s %-*s %-*s %s",
2346 	    "LINES", "IDLE", typewidth, "TYPE", namewidth, "NAME",
2347 	    hostwidth, "HOST", "PORT");
2348     for (i = 0; i < socks.size; i++) {
2349 	sock = socks.ptrs[i];
2350         nnew = sock->world->screen->nnew;
2351         nold = sock->world->screen->nback - nnew;
2352         if (shortflag) {
2353             oputs(sock->world->name);
2354             continue;
2355         }
2356         if (sock == fsock)
2357             sprintf(linebuf, "%8s", "fg");
2358         else {
2359 	    if (nold) {
2360 		if (nold > 999)
2361 		    sprintf(linebuf, "%2dk", nold / 1000);
2362 		else
2363 		    sprintf(linebuf, "%3d", nold);
2364 		if (nnew > 9999)
2365 		    sprintf(linebuf+3, "+%3dk", nnew / 1000);
2366 		else
2367 		    sprintf(linebuf+3, "+%4d", nnew);
2368 	    } else {
2369 		if (nnew > 99999)
2370 		    sprintf(linebuf, "%7dk", nnew / 1000);
2371 		else
2372 		    sprintf(linebuf, "%8d", nnew);
2373 	    }
2374 	}
2375         t = now - sock->time[SOCK_RECV].tv_sec;
2376         if (t < (60))
2377             sprintf(idlebuf, "%3ds", t);
2378         else if ((t /= 60) < 60)
2379             sprintf(idlebuf, "%3dm", t);
2380         else if ((t /= 60) < 24)
2381             sprintf(idlebuf, "%3dh", t);
2382         else if ((t /= 24) < 1000)
2383             sprintf(idlebuf, "%3dd", t);
2384         else
2385             sprintf(idlebuf, "long");
2386 
2387 	state =
2388 	    sock->constate < SS_CONNECTED ? '?' :
2389             sock->constate >= SS_ZOMBIE ? '!' :
2390 	    sock->constate == SS_OPEN ? 'O' :
2391 	    sock->constate == SS_CONNECTED && sock->fsastate == TN_SB ? 'S' :
2392 #if HAVE_SSL
2393 	    sock->constate == SS_CONNECTED && sock->ssl ? 'X' :
2394 #endif
2395 	    sock->constate == SS_CONNECTED ? 'C' :
2396 	    '#' /* shouldn't happen */;
2397 	if (sock->flags & SOCKCOMPRESS)
2398 	    state = lcase(state);
2399 	if (!numeric && sock->addr)
2400 	    sprintf(addrbuf, "%-*.*s %.6s",
2401 		hostwidth, hostwidth, sock->host, sock->port);
2402         oprintf("%c%c%c"
2403 	    " %s %s %-*.*s %-*.*s %s",
2404             (sock == xsock ? '*' : ' '),
2405 	    state,
2406 	    (sock->flags & SOCKPROXY ? 'P' : ' '),
2407             linebuf, idlebuf,
2408             typewidth, typewidth, sock->world->type,
2409 	    namewidth, namewidth, sock->world->name,
2410 	    !sock->addr ? "" : numeric ? printai(sock->addr, "%-20.20s %d") :
2411 		addrbuf);
2412     }
2413 
2414 listsocket_error:
2415     free_pattern(&pat_name);
2416     free_pattern(&pat_type);
2417 
2418     return newint(socks.size);
2419 }
2420 
handle_send_function(conString * string,const char * world,const char * flags)2421 int handle_send_function(conString *string, const char *world,
2422     const char *flags)
2423 {
2424     const char *p;
2425     int result = 0, eol_flag = 1, hook_flag = 0;
2426     Sock *old_xsock = xsock;
2427 
2428     for (p = flags; *p; p++) {
2429 	switch (*p) {
2430 	case 'o': /* for backward compatability */
2431 	    break;
2432 	case '1': case 'n': /* for backward compatability */
2433 	    eol_flag = 1; break;
2434 	case 'u': /* fall through */
2435 	case '0': case 'f': /* for backward compatability */
2436 	    eol_flag = 0; break;
2437 	case 'h':
2438 	    hook_flag = 1; break;
2439 	default:
2440 	    eprintf("invalid flag %c", *p);
2441 	    return 0;
2442 	}
2443     }
2444 
2445     xsock = (!world || !*world) ? xsock : find_sock(world);
2446     if (!hook_flag || !do_hook(H_SEND, NULL, "%S", string))
2447 	result = send_line(string->data, string->len, eol_flag);
2448     xsock = old_xsock;
2449     return result;
2450 }
2451 
handle_fake_recv_function(conString * string,const char * world,const char * flags)2452 int handle_fake_recv_function(conString *string, const char *world,
2453     const char *flags)
2454 {
2455     Sock *sock;
2456     int raw = 0;
2457     const char *p;
2458 
2459     for (p = flags; *p; p++) {
2460 	switch (*p) {
2461 	case 'r': raw = 1; break;
2462 	default:
2463 	    eprintf("invalid flag %c", *p);
2464 	    return 0;
2465 	}
2466     }
2467 
2468     sock = (!world || !*world) ? xsock : find_sock(world);
2469     if (!sock ||
2470 	sock->constate <= SS_CONNECTING || sock->constate >= SS_ZOMBIE)
2471     {
2472         eprintf("no open world %s", world ? world : "");
2473 	return 0;
2474     }
2475     if (raw)
2476 	handle_socket_input(string->data, string->len);
2477     else
2478 	queue_socket_line(sock, string, 0, 0);
2479     return 1;
2480 }
2481 
2482 
2483 /* tramsmit text to current socket */
transmit(const char * str,unsigned int numtowrite)2484 static int transmit(const char *str, unsigned int numtowrite)
2485 {
2486     int numwritten, err;
2487 
2488     if (!xsock || xsock->constate != SS_CONNECTED)
2489         return 0;
2490     while (numtowrite) {
2491 #if HAVE_SSL
2492 	if (xsock->ssl) {
2493 	    numwritten = SSL_write(xsock->ssl, str, numtowrite);
2494 	    if (numwritten <= 0) {
2495 		zombiesock(xsock); /* before hook, so sock state is correct */
2496 		ssl_io_err(xsock, numwritten, H_DISCONNECT);
2497 		return 0;
2498 	    }
2499 	} else
2500 #endif /* HAVE_SSL */
2501 	{
2502 	    numwritten = send(xsock->fd, str, numtowrite, 0);
2503 	    if (numwritten < 0) {
2504 		err = errno;
2505 		/* Socket is blocking; EAGAIN and EWOULDBLOCK are impossible. */
2506 		if (err == EINTR) {
2507 		    return 0;
2508 		} else if (err == EHOSTUNREACH || err == ENETUNREACH) {
2509 		    /* XXX there should be an UNREACHABLE hook here */
2510 		    eprintf("%s: send: %s", xsock->world->name, strerror(err));
2511 		    return 0;
2512 		} else {
2513 		    flushxsock();
2514 		    zombiesock(xsock); /* before hook, so state is correct */
2515 		    DISCON(xsock->world->name, "send", strerror(err));
2516 		    return 0;
2517 		}
2518 	    }
2519 	}
2520         numtowrite -= numwritten;
2521         str += numwritten;
2522         gettime(&xsock->time[SOCK_SEND]);
2523     }
2524     return 1;
2525 }
2526 
2527 /* send_line
2528  * Send a line to the server on the current socket.  If there is a prompt
2529  * associated with the current socket, clear it.
2530  * RFCs 854 and 1123 technically forbid sending 8-bit data in non-BINARY mode;
2531  * but if the user types it, we send it regardless of BINARY mode, and trust
2532  * the user to know what he's doing.  Some servers accept it, some strip the
2533  * high bit, some ignore the characters.
2534  */
send_line(const char * src,unsigned int len,int eol_flag)2535 int send_line(const char *src, unsigned int len, int eol_flag)
2536 {
2537     int max;
2538     int i = 0, j = 0;
2539     static char *buf = NULL;
2540     static int buflen = 0;
2541 
2542     if (!xsock ||
2543 	(xsock->constate != SS_CONNECTED && !(xsock->flags & SOCKECHO)))
2544     {
2545         eprintf("Not connected.");
2546         return 0;
2547     }
2548 
2549     if (xsock && xsock->prompt) {
2550         /* Not the same as unprompt(): we keep attrs, and delete buffer. */
2551 	if (!(xsock->flags & SOCKPROMPT)) {
2552 	    /* Prompt was implicit, so there's still a copy in xsock->buffer */
2553 	    Stringtrunc(xsock->buffer, 0);
2554 	} else {
2555 	    /* Prompt was explicit, so anything in xsock->buffer is an
2556 	     * unrelated partial line that we must keep. */
2557 	}
2558         conStringfree(xsock->prompt);
2559         xsock->prompt = NULL;
2560         xsock->prepromptattrs = 0;
2561         if (xsock == fsock) update_prompt(xsock->prompt, 1);
2562     }
2563 
2564     if (secho) {
2565 	String *str = Stringnew(NULL, 0, 0);
2566 	Sprintf(str, "%S%.*s%A", sprefix, len, src, getattrvar(VAR_secho_attr));
2567 	world_output(xsock->world, CS(str));
2568     }
2569 
2570     max = 2 * len + 3;
2571     if (buflen < max) {
2572         buf = XREALLOC(buf, buflen = max);
2573     }
2574     while (j < len) {
2575         if (xsock->flags & SOCKTELNET && src[j] == TN_IAC)
2576             buf[i++] = TN_IAC;    /* double IAC */
2577         buf[i] = unmapchar(src[j]);
2578         i++, j++;
2579     }
2580 
2581     if (eol_flag) {
2582         /* In telnet NVT mode, append CR LF; in telnet BINARY mode,
2583          * append LF, CR, or CR LF, according to variable.
2584          */
2585         if (!TELOPT(xsock, us, TN_BINARY) || binary_eol != EOL_LF)
2586             buf[i++] = '\r';
2587         if (!TELOPT(xsock, us, TN_BINARY) || binary_eol != EOL_CR)
2588             buf[i++] = '\n';
2589     }
2590 
2591     if (xsock->flags & SOCKECHO)
2592 	handle_socket_input(buf, i);
2593     if (xsock->constate == SS_CONNECTED)
2594 	return transmit(buf, i);
2595     return 1;
2596 }
2597 
handle_socket_lines(void)2598 static void handle_socket_lines(void)
2599 {
2600     static int depth = 0;
2601     conString *line;
2602     int is_prompt;
2603 
2604     if (depth) return;	/* don't recurse */
2605     if (!(line = dequeue(&xsock->queue)))
2606 	return;
2607     depth++;
2608     do {
2609 	if (!xsock->queue.list.head) /* just dequeued the last line */
2610 	    socks_with_lines--;
2611 
2612 	if (line->attrs & (F_TFPROMPT)) {
2613 	    incoming_text = line;
2614 	    handle_prompt(incoming_text, 0, TRUE);
2615 	    continue;
2616 	}
2617 
2618 	incoming_text = decode_ansi(line->data, xsock->attrs, emulation,
2619 	    &xsock->attrs);
2620 	incoming_text->time = line->time;
2621 	is_prompt = line->attrs & F_SERVPROMPT;
2622 	conStringfree(line);
2623 	incoming_text->links++;
2624 
2625 	if (is_prompt) {
2626 	    if (do_hook(H_PROMPT, NULL, "%S", incoming_text)) {
2627 		Stringfree(incoming_text);
2628 	    } else {
2629 		handle_prompt(incoming_text, 0, TRUE);
2630 	    }
2631 
2632 	} else {
2633 	    if (borg || hilite || gag) {
2634 		if (find_and_run_matches(NULL, -1, &incoming_text, xworld(),
2635 		    TRUE, 0))
2636 		{
2637 		    if (xsock != fsock)
2638 			do_hook(H_BGTRIG, "%% Trigger in world %s", "%s %S",
2639 			    xsock->world->name, incoming_text);
2640 		}
2641 	    }
2642 
2643 	    if (is_bamf(incoming_text->data) || is_quiet(incoming_text->data) ||
2644 		is_watchdog(xsock->world->history, incoming_text) ||
2645 		is_watchname(xsock->world->history, incoming_text))
2646 	    {
2647 		incoming_text->attrs |= F_GAG;
2648 	    }
2649 
2650 	    world_output(xsock->world, CS(incoming_text));
2651 	    Stringfree(incoming_text);
2652 	}
2653     } while ((line = dequeue(&xsock->queue)));
2654     depth--;
2655 
2656     /* We just emptied the queue; there may be a partial line pending */
2657     test_prompt();
2658 }
2659 
2660 /* log, record, and display line as if it came from sock */
world_output(World * world,conString * line)2661 void world_output(World *world, conString *line)
2662 {
2663     Sock *saved_xsock = xsock;
2664     xsock = world ? world->sock : NULL;
2665     line->links++;
2666     recordline(world->history, line);
2667     record_global(line);
2668     if (world->sock && (world->sock->constate < SS_DEAD) &&
2669 	!(gag && (line->attrs & F_GAG)))
2670     {
2671         if (world->sock == fsock) {
2672             screenout(line);
2673         } else {
2674 	    static int preactivity_depth = 0; /* avoid recursion */
2675 	    /* line was already tested for gag, so it WILL print */
2676 	    if (!preactivity_depth && !world->screen->active) {
2677 		preactivity_depth++;
2678                 do_hook(H_PREACTIVITY, NULL, "%s", world->name);
2679 		preactivity_depth--;
2680 	    }
2681             enscreen(world->screen, line); /* ignores preactivity_depth */
2682             if (!preactivity_depth) {
2683 		if (!world->screen->active && !(line->attrs & F_NOACTIVITY)) {
2684 		    world->screen->active = 1;
2685 		    ++active_count;
2686 		    update_status_field(NULL, STAT_ACTIVE);
2687 		    do_hook(H_ACTIVITY, "%% Activity in world %s", "%s",
2688 			world->name);
2689 		}
2690 		do_hook(H_BGTEXT, NULL, "%s", world->name);
2691             }
2692         }
2693     }
2694     conStringfree(line);
2695     xsock = saved_xsock;
2696 }
2697 
2698 /* get the prompt for the fg sock */
fgprompt(void)2699 conString *fgprompt(void)
2700 {
2701     return (fsock) ? fsock->prompt : NULL;
2702 }
2703 
tog_lp(Var * var)2704 int tog_lp(Var *var)
2705 {
2706     if (!fsock) {
2707         /* do nothing */
2708     } else if (lpflag) {
2709         if (!fsock->queue.list.head && fsock->buffer->len) {
2710             fsock->prompt = CS(decode_ansi(fsock->buffer->data, fsock->attrs,
2711                 emulation, &fsock->attrs));
2712             fsock->prompt->links++;
2713             set_refresh_pending(REF_PHYSICAL);
2714         }
2715     } else {
2716         if (fsock->prompt && !(fsock->flags & SOCKPROMPT)) {
2717             unprompt(fsock, 1);
2718             set_refresh_pending(REF_PHYSICAL);
2719         }
2720     }
2721     return 1;
2722 }
2723 
handle_prompt_func(conString * str)2724 int handle_prompt_func(conString *str)
2725 {
2726     if (xsock)
2727 	queue_socket_line(xsock, str, 0, F_TFPROMPT);
2728     return !!xsock;
2729 }
2730 
handle_prompt(String * str,int offset,int confirmed)2731 static void handle_prompt(String *str, int offset, int confirmed)
2732 {
2733     runall(1, xsock->world);	/* run prompted processes */
2734     if (xsock->prompt) {
2735         unprompt(xsock, 0);
2736     }
2737     assert(str->links == 1);
2738     xsock->prompt = CS(str);
2739     /* Old versions did trigger checking here.  Removing it breaks
2740      * compatibility, but I doubt many users will care.  Leaving
2741      * it in would not be right for /prompt.
2742      */
2743     if (xsock == fsock) update_prompt(xsock->prompt, 1);
2744     if (confirmed) xsock->flags |= SOCKPROMPT;
2745     else xsock->flags &= ~SOCKPROMPT;
2746     xsock->numquiet = 0;
2747 }
2748 
handle_implicit_prompt(void)2749 static void handle_implicit_prompt(void)
2750 {
2751     String *new;
2752 
2753     xsock->prompt_timeout = tvzero;
2754     xsock->prepromptattrs = xsock->attrs; /* save attrs for unprompt() */
2755 
2756     new = decode_ansi(xsock->buffer->data, xsock->attrs, emulation,
2757 	&xsock->attrs);
2758     new->links++;
2759 
2760     handle_prompt(new, 0, FALSE);
2761 }
2762 
2763 /* undo the effects of a false prompt */
unprompt(Sock * sock,int update)2764 static void unprompt(Sock *sock, int update)
2765 {
2766     if (!sock || !sock->prompt || !(sock->flags & SOCKPROMPT)) return;
2767     sock->attrs = sock->prepromptattrs;  /* restore original attrs */
2768     conStringfree(sock->prompt);
2769     sock->prompt = NULL;
2770     sock->prepromptattrs = 0;
2771     if (update) update_prompt(sock->prompt, 1);
2772 }
2773 
schedule_prompt(Sock * sock)2774 static void schedule_prompt(Sock *sock)
2775 {
2776     if (prompt_timeout.tv_sec == 0 ||
2777 	tvcmp(&sock->prompt_timeout, &prompt_timeout) < 0)
2778     {
2779 	prompt_timeout = sock->prompt_timeout;
2780     }
2781 }
2782 
test_prompt(void)2783 static void test_prompt(void)
2784 {
2785     if (lpflag && !xsock->queue.list.head && xsock->buffer->len) {
2786 	if (do_hook(H_PROMPT, NULL, "%S", xsock->buffer)) {
2787 	    /* The hook took care of the unterminated line. */
2788 	    Stringtrunc(xsock->buffer, 0);
2789 	} else if (lpflag) {
2790 	    /* Wait for prompt_wait before treating unterm'd line as prompt. */
2791 	    struct timeval now;
2792 	    gettime(&now);
2793 	    tvadd(&xsock->prompt_timeout, &now, &prompt_wait);
2794 	    schedule_prompt(xsock);
2795 	}
2796     }
2797 }
2798 
telnet_subnegotiation(void)2799 static void telnet_subnegotiation(void)
2800 {
2801     char *p;
2802     int ttype;
2803     static conString enum_ttype[] = {
2804         STRING_LITERAL("TINYFUGUE"),
2805         STRING_LITERAL("ANSI-ATTR"),
2806         STRING_LITERAL("ANSI"), /* a lie, but probably has the desired effect */
2807         STRING_LITERAL("UNKNOWN"),
2808         STRING_NULL };
2809 
2810     telnet_debug("recv", xsock->subbuffer->data, xsock->subbuffer->len);
2811     Stringtrunc(xsock->subbuffer, xsock->subbuffer->len - 2);
2812     p = xsock->subbuffer->data + 2;
2813     switch (*p) {
2814     case TN_TTYPE:
2815 	if (!TELOPT(xsock, us, *p)) {
2816 	    no_reply("option was not agreed on");
2817 	    break;
2818 	}
2819         if (*++p != '\01' || xsock->subbuffer->len != 4) {
2820 	    no_reply("invalid syntax");
2821 	    break;
2822 	}
2823         Sprintf(telbuf, "%c%c%c%c", TN_IAC, TN_SB, TN_TTYPE, '\0');
2824         ttype = ++xsock->ttype;
2825         if (!enum_ttype[ttype].data) { ttype--; xsock->ttype = -1; }
2826         SStringcat(telbuf, &enum_ttype[ttype]);
2827         Sappendf(telbuf, "%c%c", TN_IAC, TN_SE);
2828         telnet_send(telbuf);
2829         break;
2830     case TN_COMPRESS:
2831     case TN_COMPRESS2:
2832 	if (!TELOPT(xsock, them, *p)) {
2833 	    no_reply("option was not agreed on");
2834 	    break;
2835 	}
2836 	xsock->flags |= SOCKCOMPRESS;
2837 	break;
2838     default:
2839 	no_reply("unknown option");
2840         break;
2841     }
2842     Stringtrunc(xsock->subbuffer, 0);
2843 }
2844 
f_telnet_recv(int cmd,int opt)2845 static void f_telnet_recv(int cmd, int opt)
2846 {
2847     if (telopt) {
2848         char buf[4];
2849         sprintf(buf, "%c%c%c", TN_IAC, cmd, opt);
2850         telnet_debug("recv", buf,
2851             (cmd==(UCHAR)TN_DO || cmd==(UCHAR)TN_DONT ||
2852              cmd==(UCHAR)TN_WILL || cmd==(UCHAR)TN_WONT) ?
2853              3 : 2);
2854     }
2855 }
2856 
2857 #if HAVE_MCCP
new_zstream(void)2858 static z_stream *new_zstream(void)
2859 {
2860     z_stream *zstream;
2861     if (!(zstream = MALLOC(sizeof(z_stream))))
2862 	return NULL;
2863     zstream->zalloc = Z_NULL;
2864     zstream->zfree = Z_NULL;
2865     zstream->opaque = Z_NULL;
2866     if (inflateInit(zstream) == Z_OK)
2867 	return zstream;
2868     if (zstream->msg)
2869 	eprintf("unable to start compressed stream: %s", zstream->msg);
2870     FREE(zstream);
2871     return NULL;
2872 }
2873 #endif /* HAVE_MCCP */
2874 
2875 /* handle input from current socket */
handle_socket_input(const char * simbuffer,int simlen)2876 static int handle_socket_input(const char *simbuffer, int simlen)
2877 {
2878     char rawchar, localchar, inbuffer[4096];
2879     const char *buffer, *place;
2880 #if HAVE_MCCP
2881     char outbuffer[4096];
2882 #endif
2883     fd_set readfds;
2884     int count, n, received = 0;
2885     struct timeval timeout;
2886 
2887     if (xsock->constate <= SS_CONNECTING || xsock->constate >= SS_ZOMBIE)
2888 	return 0;
2889 
2890     if (xsock->prompt && !(xsock->flags & SOCKPROMPT)) {
2891         /* We assumed last text was a prompt, but now we have more text, so
2892          * we now assume that they are both part of the same long line.  (If
2893          * we're wrong, the previous prompt appears as output.  But if we did
2894          * the opposite, a real begining of a line would never appear in the
2895          * output window; that would be a worse mistake.)
2896 	 * Note that a terminated (EOR or GOAHEAD) prompt will NOT be cleared
2897 	 * when new text arrives (it will only be cleared when there is a new
2898 	 * prompt).
2899          */
2900         unprompt(xsock, xsock==fsock);
2901     }
2902     xsock->prompt_timeout = tvzero;
2903 
2904     do {  /* while there are more data to be processed */
2905 	if (simbuffer) {
2906 	    buffer = simbuffer;
2907 	    count = simlen;
2908 	} else {
2909 #if HAVE_MCCP
2910 	    if (xsock->zstream && xsock->zstream->avail_in) {
2911 		count = 0;  /* no reading */
2912 	    } else
2913 #endif
2914 #if HAVE_SSL
2915 	    if (xsock->ssl) {
2916 		count = SSL_read(xsock->ssl, inbuffer, sizeof(inbuffer));
2917 		if (count == 0 &&
2918 		    SSL_get_error(xsock->ssl, 0) == SSL_ERROR_SYSCALL &&
2919 		    ERR_peek_error() == 0)
2920 		{
2921 		    /* Treat a count of 0 with no errors as a normal EOF */
2922 		    goto eof;
2923 		} else if (count <= 0) {
2924 		    /* Treat an error or a bad EOF as an error */
2925 		    zombiesock(xsock); /* before hook, so state is correct */
2926 		    ssl_io_err(xsock, count, H_DISCONNECT);
2927 		    return received;
2928 		}
2929 	    } else
2930 #endif
2931 	    {
2932 		/* We could loop while (count < 0 && errno == EINTR), but if we
2933 		 * got here because of a mistake in the active fdset and there
2934 		 * is really nothing to read, the loop would be unbreakable. */
2935 		count = recv(xsock->fd, inbuffer, sizeof(inbuffer), 0);
2936 		eof:
2937 		if (count <= 0) {
2938 		    int err = errno;
2939 		    constate_t state = xsock->constate;
2940 		    if (count < 0 && errno == EINTR)
2941 			return 0;
2942 		    /* Socket is blocking; EAGAIN and EWOULDBLOCK impossible. */
2943 		    if (xsock->buffer->len) {
2944 			queue_socket_line(xsock, CS(xsock->buffer), 0, 0);
2945 			Stringtrunc(xsock->buffer, 0);
2946 		    }
2947 		    flushxsock();
2948 		    /* On some systems, a socket that failed nonblocking connect
2949 		     * selects readable instead of writable.  If SS_CONNECTING,
2950 		     * that's what happened, so we do CONFAIL not DISCONNECT.
2951 		     */
2952 		    zombiesock(xsock); /* before hook, so constate is correct */
2953 		    if (state == SS_CONNECTING)
2954 			CONFAIL(xsock, "recv", strerror(err));
2955 		    else do_hook(H_DISCONNECT, (count < 0) ?
2956 			"%% Connection to %s closed: %s: %s" :
2957 			"%% Connection to %s closed by foreign host.",
2958 			(count < 0) ? "%s %s %s" : "%s",
2959 			xsock->world->name, "recv", strerror(err));
2960 		    return received;
2961 		}
2962 	    }
2963 #if HAVE_MCCP
2964 	    if (xsock->zstream) {
2965 		int zret;
2966 		if (count) {
2967 		    xsock->zstream->next_in = (Bytef*)inbuffer;
2968 		    xsock->zstream->avail_in = count;
2969 		}
2970 		xsock->zstream->next_out = (Bytef*)(buffer = outbuffer);
2971 		xsock->zstream->avail_out = sizeof(outbuffer);
2972 		zret = inflate(xsock->zstream, Z_PARTIAL_FLUSH);
2973 		switch (zret) {
2974 		case Z_OK:
2975 		    count = (char*)xsock->zstream->next_out - outbuffer;
2976 		    break;
2977 		case Z_STREAM_END:
2978 		    /* handle stuff inflated before stream end */
2979 		    count = (char*)xsock->zstream->next_out - outbuffer;
2980 		    received += handle_socket_input(outbuffer, count);
2981 		    /* prepare to handle noncompressed stuff after stream end */
2982 		    buffer = (char*)xsock->zstream->next_in;
2983 		    count = xsock->zstream->avail_in;
2984 		    /* clean up zstream */
2985 		    inflateEnd(xsock->zstream);
2986 		    FREE(xsock->zstream);
2987 		    xsock->zstream = NULL;
2988 		    xsock->flags &= ~SOCKCOMPRESS;
2989 		    break;
2990 		default:
2991 		    flushxsock();
2992 		    zombiesock(xsock); /* before hook, so constate is correct */
2993 		    DISCON(xsock->world->name, "inflate",
2994 			xsock->zstream->msg ? xsock->zstream->msg : "unknown");
2995 		    return received;
2996 		}
2997 	    } else
2998 #endif
2999 		buffer = inbuffer;
3000 	}
3001 
3002         for (place = buffer; place - buffer < count; place++) {
3003 
3004             /* We always accept 8-bit data, even though RFCs 854 and 1123
3005              * say server shouldn't transmit it unless in BINARY mode.  What
3006              * we do with it depends on the locale.
3007              */
3008             rawchar = *place;
3009             localchar = localize(rawchar);
3010 
3011             /* Telnet processing
3012              * If we're not sure yet whether server speaks telnet protocol,
3013              * we still accept it, but if an invalid telnet command arrives,
3014              * we leave it alone and disable telnet processing.
3015              */
3016             if (xsock->fsastate == TN_IAC &&
3017                 xsock->flags & (SOCKTELNET | SOCKMAYTELNET))
3018             {
3019                 int valid = 0;
3020                 switch (xsock->fsastate = rawchar) {
3021                 case TN_GA: case TN_EOR:
3022                     /* This is definitely a prompt. */
3023                     telnet_recv(rawchar, 0);
3024 		    queue_socket_line(xsock, CS(xsock->buffer), 0, F_SERVPROMPT);
3025 		    Stringtrunc(xsock->buffer, 0);
3026                     break;
3027                 case TN_SB:
3028 		    if (!(xsock->flags & SOCKTELNET)) {
3029 			/* Telnet subnegotiation can't happen without a
3030 			 * previous telnet option negotation, so treat the
3031 			 * IAC SB as non-telnet, and disable telnet. */
3032 			xsock->flags &= ~SOCKMAYTELNET;
3033 			place--;
3034 			rawchar = xsock->fsastate;
3035 			goto non_telnet;
3036 		    }
3037                     Sprintf(xsock->subbuffer, "%c%c", TN_IAC, TN_SB);
3038                     xsock->substate = '\0';
3039                     break;
3040                 case TN_WILL: case TN_WONT:
3041                 case TN_DO:   case TN_DONT:
3042                     /* just change state */
3043                     break;
3044                 case TN_IAC:
3045                     Stringadd(xsock->buffer, localchar);  /* literal IAC */
3046                     xsock->fsastate = '\0';
3047                     break;
3048 
3049                 case TN_NOP:
3050                 case TN_DATA_MARK:
3051                 case TN_BRK:
3052                 case TN_IP:
3053                 case TN_AO:
3054                 case TN_AYT:
3055                 case TN_EC:
3056                 case TN_EL:
3057                     valid = 1;
3058 		    /* Unsupported.  Fall through to default case. */
3059                 default:
3060                     if (xsock->flags & SOCKTELNET ||
3061                         (xsock->flags & SOCKMAYTELNET && valid))
3062                     {
3063                         /* unsupported or invalid telnet command */
3064                         telnet_recv(rawchar, 0);
3065                         xsock->fsastate = '\0';
3066                         break;
3067                     }
3068                     /* Invalid telnet command, and telnet protocol hasn't been
3069                      * established, so treat the IAC and rawchar as non-telnet,
3070                      * and disable telnet. */
3071                     xsock->flags &= ~SOCKMAYTELNET;
3072                     place--;
3073                     rawchar = xsock->fsastate;
3074                     goto non_telnet;
3075                 }
3076 
3077                 if (!(xsock->flags & SOCKTELNET)) {
3078                     /* We now know server groks TELNET */
3079                     xsock->flags |= SOCKTELNET;
3080                     preferred_telnet_options();
3081                 }
3082                 continue;  /* avoid non-telnet processing */
3083 
3084             } else if (xsock->fsastate == TN_SB) {
3085 		if (xsock->subbuffer->len > 255) {
3086 		    /* It shouldn't take this long; server is broken.  Abort. */
3087 		    SStringcat(xsock->buffer, CS(xsock->subbuffer));
3088 		    Stringtrunc(xsock->subbuffer, 0);
3089 		} else if (xsock->substate == TN_IAC) {
3090                     if (rawchar == TN_SE) {
3091 			Sappendf(xsock->subbuffer, "%c%c", TN_IAC, TN_SE);
3092                         xsock->fsastate = '\0';
3093                         telnet_subnegotiation();
3094                     } else {
3095                         Stringadd(xsock->subbuffer, rawchar);
3096                         xsock->substate = '\0';
3097                     }
3098                 } else if (rawchar == TN_IAC) {
3099                     xsock->substate = TN_IAC;
3100                 } else {
3101                     Stringadd(xsock->subbuffer, rawchar);
3102                     xsock->substate = '\0';
3103 #if HAVE_MCCP /* hack for broken MCCPv1 subnegotiation */
3104 		    if (xsock->subbuffer->len == 5 &&
3105 			memcmp(xsock->subbuffer->data, mccp1_subneg, 5) == 0)
3106 		    {
3107 			xsock->fsastate = '\0';
3108 			telnet_subnegotiation();
3109 		    }
3110 #endif
3111                 }
3112 #if HAVE_MCCP
3113 		if (xsock->flags & SOCKCOMPRESS && !xsock->zstream) {
3114 		    /* compression was just enabled. */
3115 		    xsock->zstream = new_zstream();
3116 		    if (!xsock->zstream) {
3117 			zombiesock(xsock);
3118 		    } else {
3119 			xsock->zstream->next_in = (Bytef*)++place;
3120 			xsock->zstream->avail_in = count - (place - buffer);
3121 		    }
3122 		    count = 0; /* abort the buffer scan */
3123 		}
3124 #endif
3125                 continue;  /* avoid non-telnet processing */
3126 
3127             } else if (xsock->fsastate == TN_WILL) {
3128                 xsock->fsastate = '\0';
3129                 telnet_recv(TN_WILL, rawchar);
3130                 if (TELOPT(xsock, them, rawchar)) { /* already there, ignore */
3131 		    no_reply("option was already agreed on");
3132                     CLR_TELOPT(xsock, them_tog, rawchar);
3133                 } else if (
3134 #if 0  /* many servers think DO SGA means character-at-a-time mode */
3135                     rawchar == TN_SGA ||
3136 #endif
3137 #if HAVE_MCCP
3138 		    (rawchar == TN_COMPRESS && mccp) ||
3139 		    (rawchar == TN_COMPRESS2 && mccp) ||
3140 #endif
3141                     rawchar == TN_ECHO ||
3142                     rawchar == TN_SEND_EOR ||
3143                     rawchar == TN_BINARY)              /* accept any of these */
3144                 {
3145                     SET_TELOPT(xsock, them, rawchar);  /* set state */
3146                     if (TELOPT(xsock, them_tog, rawchar)) {/* we requested it */
3147                         CLR_TELOPT(xsock, them_tog, rawchar);  /* done */
3148                     } else {
3149                         DO(rawchar);  /* acknowledge their request */
3150                     }
3151                 } else {
3152                     DONT(rawchar);    /* refuse their request */
3153                 }
3154                 continue;  /* avoid non-telnet processing */
3155 
3156             } else if (xsock->fsastate == TN_WONT) {
3157                 xsock->fsastate = '\0';
3158                 telnet_recv(TN_WONT, rawchar);
3159                 if (!TELOPT(xsock, them, rawchar)) { /* already there, ignore */
3160 		    no_reply("option was already agreed on");
3161                     CLR_TELOPT(xsock, them_tog, rawchar);
3162                 } else {
3163                     CLR_TELOPT(xsock, them, rawchar);  /* set state */
3164                     if (TELOPT(xsock, them_tog, rawchar)) { /* we requested */
3165                         CLR_TELOPT(xsock, them_tog, rawchar);  /* done */
3166                     } else {
3167                         DONT(rawchar);  /* acknowledge their request */
3168                     }
3169                 }
3170                 continue;  /* avoid non-telnet processing */
3171 
3172             } else if (xsock->fsastate == TN_DO) {
3173                 xsock->fsastate = '\0';
3174                 telnet_recv(TN_DO, rawchar);
3175                 if (TELOPT(xsock, us, rawchar)) { /* already there, ignore */
3176 		    no_reply("option was already agreed on");
3177                     CLR_TELOPT(xsock, them_tog, rawchar);
3178                 } else if (
3179                     rawchar == TN_NAWS ||
3180                     rawchar == TN_TTYPE ||
3181                     rawchar == TN_BINARY)
3182                 {
3183                     SET_TELOPT(xsock, us, rawchar);  /* set state */
3184                     if (TELOPT(xsock, us_tog, rawchar)) { /* we requested it */
3185                         CLR_TELOPT(xsock, us_tog, rawchar);  /* done */
3186                     } else {
3187                         WILL(rawchar);  /* acknowledge their request */
3188                     }
3189                     if (rawchar == TN_NAWS) do_naws(xsock);
3190                 } else {
3191                     WONT(rawchar);      /* refuse their request */
3192                 }
3193                 continue;  /* avoid non-telnet processing */
3194 
3195             } else if (xsock->fsastate == TN_DONT) {
3196                 xsock->fsastate = '\0';
3197                 telnet_recv(TN_DONT, rawchar);
3198                 if (!TELOPT(xsock, us, rawchar)) { /* already there, ignore */
3199 		    no_reply("option was already agreed on");
3200                     CLR_TELOPT(xsock, us_tog, rawchar);
3201                 } else {
3202                     CLR_TELOPT(xsock, us, rawchar);  /* set state */
3203                     if (TELOPT(xsock, us_tog, rawchar)) { /* we requested */
3204                         CLR_TELOPT(xsock, us_tog, rawchar);  /* done */
3205                     } else {
3206                         WONT(rawchar);  /* acknowledge their request */
3207                     }
3208                 }
3209                 continue;  /* avoid non-telnet processing */
3210 
3211             } else if (rawchar == TN_IAC &&
3212                 xsock->flags & (SOCKTELNET | SOCKMAYTELNET))
3213             {
3214                 xsock->fsastate = rawchar;
3215                 continue;  /* avoid non-telnet processing */
3216             }
3217 
3218             /* non-telnet processing*/
3219 non_telnet:
3220             if (rawchar == '\n') {
3221                 /* Complete line received.  Queue it. */
3222                 queue_socket_line(xsock, CS(xsock->buffer), 0, 0);
3223 		Stringtrunc(xsock->buffer, 0);
3224                 xsock->fsastate = rawchar;
3225 
3226             } else if (emulation == EMUL_DEBUG) {
3227                 if (localchar != rawchar)
3228                     Stringcat(xsock->buffer, "M-");
3229                 if (is_print(localchar))
3230                     Stringadd(xsock->buffer, localchar);
3231                 else {
3232                     Stringadd(xsock->buffer, '^');
3233                     Stringadd(xsock->buffer, CTRL(localchar));
3234                 }
3235                 xsock->fsastate = '\0';
3236 
3237             } else if (rawchar == '\r' || rawchar == '\0') {
3238                 /* Ignore CR and NUL. */
3239                 xsock->fsastate = rawchar;
3240 
3241             } else if (rawchar == '\b' && emulation >= EMUL_PRINT &&
3242                 xsock->fsastate == '*')
3243 	    {
3244 		/* "*\b" is an LP editor prompt. */
3245 		queue_socket_line(xsock, CS(xsock->buffer), 0, F_SERVPROMPT);
3246 		Stringtrunc(xsock->buffer, 0);
3247                 xsock->fsastate = '\0';
3248 		/* other occurances of '\b' are handled by decode_ansi(), so
3249 		 * ansi codes aren't clobbered before they're interpreted */
3250 
3251             } else {
3252                 /* Normal character. */
3253                 const char *end;
3254                 Stringadd(xsock->buffer, localchar);
3255                 end = ++place;
3256                 /* Quickly skip characters that can't possibly be special. */
3257                 while (is_print(*end) && *end != TN_IAC && end - buffer < count)
3258                     end++;
3259                 Stringfncat(xsock->buffer, (char*)place, end - place);
3260                 place = end - 1;
3261                 xsock->fsastate = (*place == '*') ? '*' : '\0';
3262             }
3263         }
3264 
3265         /* See if anything arrived while we were parsing */
3266 
3267 	received += count;
3268 
3269 #if HAVE_MCCP
3270 	/* If there's still un-inflated stuff, we must process it before we
3271 	 * exit this loop.
3272 	 */
3273 	if (xsock->zstream && xsock->zstream->avail_in) {
3274 	    n = xsock->zstream->avail_in;
3275 	    continue;
3276 	}
3277 #endif
3278 
3279 	if (simbuffer || received > SPAM) break; /* after uninflated check */
3280 
3281         FD_ZERO(&readfds);
3282         FD_SET(xsock->fd, &readfds);
3283 	timeout = tvzero; /* don't use tvzero directly, select may modify it */
3284         if ((n = select(xsock->fd + 1, &readfds, NULL, NULL, &timeout)) < 0) {
3285             if (errno != EINTR) die("handle_socket_input: select", errno);
3286         }
3287 
3288 	if (interrupted()) break;
3289 
3290     } while (n > 0);
3291 
3292     test_prompt();
3293 
3294     return received;
3295 }
3296 
3297 
is_quiet(const char * str)3298 static int is_quiet(const char *str)
3299 {
3300     if (!xsock->numquiet) return 0;
3301     if (!--xsock->numquiet) return 1;
3302     /* This should not be hard coded. */
3303     if ((strncmp("Use the WHO command", str, 19) == 0) ||
3304         (strcmp("### end of messages ###", str) == 0))
3305             xsock->numquiet = 0;
3306     return 1;
3307 }
3308 
is_bamf(const char * str)3309 static int is_bamf(const char *str)
3310 {
3311     smallstr name, host, port;
3312     STATIC_BUFFER(buffer);
3313     World *world;
3314     Sock *callingsock;  /* like find_and_run_matches(), we must restore xsock */
3315 
3316     callingsock = xsock;
3317 
3318     if (!bamf || restriction >= RESTRICT_WORLD) return 0;
3319     if (sscanf(str,
3320         "#### Please reconnect to %64[^ @]@%64s (%*64[^ )]) port %64s ####",
3321         name, host, port) != 3)
3322             return 0;
3323 
3324     Stringtrunc(buffer, 0);
3325     if (bamf == BAMF_UNTER) Stringadd(buffer, '@');
3326     Stringcat(buffer, name);
3327     if (!(world = find_world(buffer->data))) {
3328         if (bamf == BAMF_UNTER && xsock) {
3329             world = new_world(buffer->data, xsock->world->type,
3330 		host, port, xsock->world->character, xsock->world->pass,
3331 		xsock->world->mfile, WORLD_TEMP, xsock->world->myhost);
3332         } else {
3333             world = new_world(buffer->data,"",host,port,"","","",WORLD_TEMP,"");
3334         }
3335     }
3336 
3337     do_hook(H_BAMF, "%% Bamfing to %s", "%s", name);
3338     if (bamf == BAMF_UNTER && xsock) killsock(xsock);
3339     if (!opensock(world, CONN_AUTOLOGIN))
3340         eputs("% Connection through portal failed.");
3341     xsock = callingsock;
3342     return 1;
3343 }
3344 
do_naws(Sock * sock)3345 static void do_naws(Sock *sock)
3346 {
3347     unsigned int width, height, i;
3348     UCHAR octet[4];
3349     Sock *old_xsock;
3350 
3351     width = (emulation != EMUL_RAW && wrapflag && wrapsize) ?
3352 	wrapsize : columns;
3353     height = winlines() + !visual;
3354 
3355     Sprintf(telbuf, "%c%c%c", TN_IAC, TN_SB, TN_NAWS);
3356     octet[0] = (width >> 8);
3357     octet[1] = (width & 0xFF);
3358     octet[2] = (height >> 8);
3359     octet[3] = (height & 0xFF);
3360     for (i = 0; i < 4; i++) {
3361         if (octet[i] == (UCHAR)TN_IAC) Stringadd(telbuf, TN_IAC);
3362         Stringadd(telbuf, octet[i]);
3363     }
3364     Sappendf(telbuf, "%c%c", TN_IAC, TN_SE);
3365 
3366     old_xsock = xsock;;
3367     xsock = sock;
3368     telnet_send(telbuf);
3369     xsock = old_xsock;
3370 }
3371 
telnet_debug(const char * dir,const char * str,int len)3372 static void telnet_debug(const char *dir, const char *str, int len)
3373 {
3374     String *buffer;
3375     int state;
3376 
3377     if (telopt) {
3378         buffer = Stringnew(NULL, 0, 0);
3379         Sprintf(buffer, "%% %s:", dir);
3380 	if (len == 0)
3381 	    Stringcat(buffer, str);
3382 	else {
3383 	    for (state = 0; len; len--, str++) {
3384 		if (*str == TN_IAC || state == TN_IAC || state == TN_SB ||
3385 		    state == TN_WILL || state == TN_WONT ||
3386 		    state == TN_DO || state == TN_DONT)
3387 		{
3388 		    if (telnet_label[(UCHAR)*str])
3389 			Sappendf(buffer, " %s", telnet_label[(UCHAR)*str]);
3390 		    else
3391 			Sappendf(buffer, " %d", (unsigned int)*str);
3392 		    state = *str;
3393 		} else if (state == TN_TTYPE) {
3394 		    if (*str == (char)0) {
3395 			Stringcat(buffer, " IS \"");
3396 			while (len--, str++, is_print(*str) && !(*str & 0x80))
3397 			    Stringadd(buffer, *str);
3398 			Stringadd(buffer, '\"');
3399 			len++, str--;
3400 		    } else if (*str == (char)1) {
3401 			Stringcat(buffer, " SEND");
3402 		    }
3403 		    state = 0;
3404 		} else {
3405 		    Sappendf(buffer, " %u", (unsigned char)*str);
3406 		    state = 0;
3407 		}
3408 	    }
3409 	}
3410         nolog++;
3411         /* norecord++; */
3412         world_output(xsock->world, CS(buffer));
3413         /* norecord--; */
3414         nolog--;
3415     }
3416 }
3417 
telnet_send(String * cmd)3418 static void telnet_send(String *cmd)
3419 {
3420     transmit(cmd->data, cmd->len);
3421     telnet_debug("sent", cmd->data, cmd->len);
3422 }
3423 
local_echo(int flag)3424 int local_echo(int flag)
3425 {
3426     if (flag < 0)
3427         return sockecho();
3428     if (!xsock || !(xsock->flags & SOCKTELNET))
3429         return 0;
3430 
3431     if (flag != sockecho()) {
3432         /* request a change */
3433         SET_TELOPT(xsock, them_tog, TN_ECHO);
3434         if (flag)
3435             DONT(TN_ECHO);
3436         else
3437             DO(TN_ECHO);
3438     }
3439     return 1;
3440 }
3441 
3442 
transmit_window_size(void)3443 void transmit_window_size(void)
3444 {
3445     Sock *sock;
3446 
3447     for (sock = hsock; sock; sock = sock->next)
3448         if (TELOPT(sock, us, TN_NAWS))
3449             do_naws(sock);
3450 }
3451 
preferred_telnet_options(void)3452 static void preferred_telnet_options(void)
3453 {
3454     SET_TELOPT(xsock, us_tog, TN_NAWS);
3455     WILL(TN_NAWS);
3456 #if 0
3457     SET_TELOPT(xsock, us_tog, TN_BINARY);
3458     WILL(TN_BINARY);		/* allow us to send 8-bit data */
3459     SET_TELOPT(xsock, them_tog, TN_BINARY);
3460     DO(TN_BINARY);		/* allow server to send 8-bit data */
3461 #endif
3462 }
3463 
3464 /* Find the named world (current world if name is blank) or print an error */
named_or_current_world(const char * name)3465 World *named_or_current_world(const char *name)
3466 {
3467     World *world;
3468     if (!(world = (*name) ? find_world(name) : xworld())) {
3469 	eprintf("No world %s", name);
3470     }
3471     return world;
3472 }
3473 
world_info(const char * worldname,const char * fieldname)3474 const char *world_info(const char *worldname, const char *fieldname)
3475 {
3476     World *world;
3477     const char *result;
3478 
3479     world = worldname ? find_world(worldname) : xworld();
3480     if (!world) return ""; /* not an error */
3481 
3482     if (!fieldname || strcmp("name", fieldname) == 0) {
3483         result = world->name;
3484     } else if (strcmp("type", fieldname) == 0) {
3485         result = world_type(world);
3486     } else if (strcmp("character", fieldname) == 0) {
3487         result = world_character(world);
3488     } else if (strcmp("password", fieldname) == 0) {
3489         result = world_pass(world);
3490     } else if (strcmp("host", fieldname) == 0) {
3491         result = worldname ? world->host : world->sock->host;
3492     } else if (strcmp("port", fieldname) == 0) {
3493         result = worldname ? world->port : world->sock->port;
3494     } else if (strcmp("mfile", fieldname) == 0) {
3495         result = world_mfile(world);
3496     } else if (strcmp("login", fieldname) == 0) {
3497         result = world->sock && world->sock->flags & SOCKLOGIN ? "1" : "0";
3498     } else if (strcmp("proxy", fieldname) == 0) {
3499         result = world->sock && world->sock->flags & SOCKPROXY ? "1" : "0";
3500     } else if (strcmp("src", fieldname) == 0) {
3501         result = worldname ? world->myhost : world->sock->myhost;
3502     } else if (strcmp("cipher", fieldname) == 0) {
3503 	result =
3504 #if HAVE_SSL
3505 	    (world->sock && world->sock->ssl) ?
3506 	    SSL_get_cipher_name(world->sock->ssl) :
3507 #endif
3508 	    "";
3509     } else return NULL;
3510     return result ? result : "";
3511 }
3512 
is_open(const char * worldname)3513 int is_open(const char *worldname)
3514 {
3515     World *w;
3516 
3517     if (!worldname || !*worldname) {
3518         if (!xsock) return 0;
3519         w = xsock->world;
3520     } else if (!(w = find_world(worldname))) {
3521         return 0;
3522     }
3523     return (w->sock && (w->sock->constate >= SS_CONNECTED) &&
3524 	(w->sock->constate < SS_ZOMBIE));
3525 }
3526 
is_connected(const char * worldname)3527 int is_connected(const char *worldname)
3528 {
3529     World *w;
3530 
3531     if (!worldname || !*worldname) {
3532         if (!xsock) return 0;
3533         w = xsock->world;
3534     } else if (!(w = find_world(worldname))) {
3535         return 0;
3536     }
3537     return (w->sock && (w->sock->constate == SS_CONNECTED));
3538 }
3539 
nactive(const char * worldname)3540 int nactive(const char *worldname)
3541 {
3542     World *w;
3543 
3544     if (!worldname || !*worldname)
3545         return active_count;
3546     if (!(w = find_world(worldname)) || !w->sock)
3547         return 0;
3548     return w->screen->active ? w->screen->nnew : 0;
3549 }
3550 
3551