1 /*---------------------------------------------------------------------------
2 * Gamedriver Communications module.
3 *
4 *---------------------------------------------------------------------------
5 * Throughout the module the fact is used that valid socket numbers
6 * are always >= 0. Unused sockets are therefore marked with negative
7 * numbers.
8 *
9 * All information needed for an interactive object are stored in
10 * a 'interactive_t'. This struct is linked to by the shadow sentence
11 * of the interactive object.
12 *
13 * Sending data is performed through the function add_message().
14 * The function collects the data in interactive.message_buf[] until
15 * it is filled (or a special 'flush' message is passed), then the
16 * data is written en-bloc to the network.
17 *
18 * Incoming data is collected in interactive.text[]. interactive.text_end
19 * indexes the first free character in the buffer where new data is to
20 * be appended. The new data is not passed directly to the command parser,
21 * instead it is processed by a dfa implementing the important parts
22 * of the telnet protocol. The dfa analyses the data read, interprets
23 * any telnet commands and stores the remaining 'pure' data starting
24 * from the beginning of .text[].
25 *
26 * Initialized to start working in the state TS_DATA, the dfa does its
27 * thing until it either reaches a line end or the end of the current
28 * data. If it is a line end, it terminates the pure data collected so
29 * far with a '\0', goes into state TS_READY, and lets .tn_end index
30 * the next unprocessed raw data char. If it is the end of the current
31 * data, the dfa stays in whatever state it was and indexes the current end
32 * of the pure data gathered so far with interactive.command_end. Once
33 * a new chunk of data has been read, the dfa simply continues where it
34 * took off.
35 *
36 * There are some variations to this scheme, but you get the idea. It is
37 * possible to do all telnet negotiations on mudlib level, but it must
38 * be either the driver or the mudlib, not both.
39 *
40 * To understand get_message() itself fully, think of it as a coroutine
41 * with its own state. It does not really return to the caller (though
42 * that is how it is implemented), in merely yields control back to
43 * caller in order to process the found command or the pending heartbeat.
44 * TODO: Obvious possibility for implementation multi-threading.
45 *
46 * Timing is implemented this way: The driver usually stays in the input
47 * loop, waiting in 1 second intervals for incoming data. An alarm() is
48 * triggered by backend.c every 2 seconds and sets the flag variable
49 * comm_time_to_call_heart_beat. The loop checks this variable every second
50 * and, if it is set, aborts its input loop and returns to the backend.
51 * To mark the cause of the return, the variable time_to_call_heart_beat is
52 * set before return.
53 *
54 * TODO: The noecho/charmode logic, especially in combination with
55 * TODO:: the telnet machine is frustratingly underdocumented.
56 *
57 * The data that can not written directly to the sockets is put instead into
58 * an intermediate buffer, from which the backend loop will continue writing
59 * when possible. The buffers are stored in a linked list in the interactive_s
60 * structure.
61 *
62 * TODO: Fiona says: The telnet code is frustrating. It would be better if
63 * TODO:: the common handling of e.g. TELNET_NAWS is offered by hooks,
64 * TODO:: as the Anarres version of MudOS does. This would mean a rewrite.
65 *---------------------------------------------------------------------------
66 */
67
68 #define SAVE_NOECHO /* TODO: Define to enable safe NOECHO mode */
69 #define SIMULATE_CHARMODE /* TODO: Even linemode clients stay in charmode */
70
71 #include "driver.h"
72 #include "typedefs.h"
73
74 #include "my-alloca.h"
75
76 #include <stdio.h>
77 #include <ctype.h>
78 #include <sys/time.h>
79 #include <stdarg.h>
80 #include <stddef.h>
81 #include <sys/ioctl.h>
82
83 #define TELOPTS
84 #include "../mudlib/sys/telnet.h"
85
86 #ifdef HAVE_NETDB_H
87 # include <netdb.h>
88 #endif
89
90 #ifdef HAVE_SYS_PARAM_H
91 # include <sys/param.h>
92 #endif
93
94 #include <signal.h>
95
96 #if defined(_AIX)
97 # include <sys/select.h>
98 #endif
99
100 #ifdef HAVE_FCNTL
101 # include <fcntl.h>
102 #endif
103
104 #ifdef SOCKET_INC
105 # include SOCKET_INC
106 #endif
107
108 #include "comm.h"
109 #include "access_check.h"
110 #include "actions.h"
111 #include "array.h"
112 #include "closure.h"
113 #include "ed.h"
114 #include "exec.h"
115 #include "filestat.h"
116 #include "gcollect.h"
117 #include "interpret.h"
118 #include "main.h"
119 #include "mstrings.h"
120 #include "object.h"
121 #include "pkg-mccp.h"
122 #include "pkg-pgsql.h"
123 #ifdef USE_TLS
124 #include "pkg-tls.h"
125 #endif
126 #include "sent.h"
127 #include "simulate.h"
128 #include "stdstrings.h"
129 #include "svalue.h"
130 #include "swap.h"
131 #include "wiz_list.h"
132 #include "xalloc.h"
133
134 #include "i-eval_cost.h"
135
136 #include "../mudlib/sys/comm.h"
137 #include "../mudlib/sys/configuration.h"
138 #include "../mudlib/sys/driver_hook.h"
139 #include "../mudlib/sys/input_to.h"
140
141 /* if driver is compiled for ERQ demon then include the necessary file
142 */
143 #ifdef ERQ_DEMON
144 # ifdef ERQ_INCLUDE
145 # include ERQ_INCLUDE
146 # else
147 # include "util/erq/erq.h"
148 # endif
149 #endif
150
151 /* When no special networking code is needed, define the
152 * socket function to their normal Unix names.
153 */
154 #if !defined (SOCKET_LIB) && !defined(SOCKET_INC)
155 # define socket_number(s) (s)
156 # define socket_ioctl ioctl
157 # ifndef hpux
158 # define socket_select select
159 # else
160 # define socket_select(n,r,w,x,t) select(n, (int *)r, (int *)w, (int *)x, t)
161 /* Silences the compiler */
162 # endif
163 # define socket_read read
164 # define socket_write write
165 # define socket_close close
166 #endif /* SOCKET_LIB */
167
168 #if defined(_AIX)
169 typedef unsigned long length_t;
170 #elif defined(__INTEL_COMPILER) || defined (__GNUC__)
171 typedef socklen_t length_t;
172 #else
173 typedef int length_t;
174 #endif
175
176 #if defined(CYGWIN)
177 extern int socketpair(int, int, int, int[2]);
178 #endif
179
180 #ifndef EPROTO
181 # define EPROTO EINTR
182 #endif
183 #ifndef SIGCLD
184 # define SIGCLD SIGCHLD
185 #endif
186
187 #ifndef MAXHOSTNAMELEN
188 # define MAXHOSTNAMELEN 64
189 #endif
190
191 #ifndef INET_ADDRSTRLEN
192 # define INET_ADDRSTRLEN 16
193 #endif
194
195 /* Amazing how complicated networking can be, hm? */
196
197 /*-------------------------------------------------------------------------*/
198 /* Types */
199
200 /* --- struct input_to_s: input_to() datastructure
201 *
202 * input-to structures describe a pending input_to() for a given
203 * interactive object. It is a specialization of input_s,
204 * which therefore must be the first element.
205 */
206 typedef struct input_to_s input_to_t;
207
208 struct input_to_s {
209 input_t input;
210 callback_t fun; /* The function to call, and its args */
211 p_uint eval_nr; /* The thread number where this started. */
212 };
213
214 /*-------------------------------------------------------------------------*/
215 /* Variables */
216
217 interactive_t *all_players[MAX_PLAYERS];
218 /* Pointers to the structures of the interactive users.
219 * Unused entries are NULL.
220 * TODO: A list would be nicer
221 */
222
223 static int max_player = -1;
224 /* Index of the last used entry in all_players[]. */
225
226 int num_player = 0;
227 /* The current number of active users */
228
229 char *message_flush = NULL;
230 /* Special flush message for add_message().
231 * It is a variable instead of a define to keep gcc from complaining about
232 * a 'null format string'.
233 */
234
235 p_int write_buffer_max_size = WRITE_BUFFER_MAX_SIZE;
236 /* Amount of data held pending in the write fifo queue.
237 * 0: No queue.
238 * -1: Infinite queue.
239 */
240
241 static char udp_buf[65536];
242 /* Buffer for incoming UDP datagrams in get_message().
243 * If it is too small, the rest of the to be received datagram will be
244 * discarded. As UDP datagrams get be as large as (65536 - UDP-Header -
245 * IP-Header) we will just play safe here.
246 * static (file-scope) buffer, because we don't want to allocate such a
247 * large buffer on the stack or by xalloc (it is used often, we're not
248 * multi-threaded nor is get_message() re-entrant).
249 * Note for IPv6: IPv6 supports so-called jumbograms with payloads up to
250 * 2^32-1 octets in length (rfc2675). Obviously, we don't support that. ;-)
251 */
252
253 #ifdef COMM_STAT
254
255 /* The statistics were originally introduced to measure the efficiency
256 * of the message buffering in comparison to the unbuffered sending of
257 * data. Nowadays, it's just interesting to know how much bandwidth you
258 * use.
259 */
260
261 unsigned long add_message_calls = 0;
262 /* Number of calls to add_message() */
263
264 unsigned long inet_packets = 0;
265 /* Number packets sent to the users */
266
267 unsigned long inet_volume = 0;
268 /* Amount of data sent to the users */
269
270 unsigned long inet_packets_in = 0;
271 /* Number packets received from the users */
272
273 unsigned long inet_volume_in = 0;
274 /* Amount of data received from the users */
275
276 #endif
277
278 /*-------------------------------------------------------------------------*/
279
280 #ifdef ERQ_DEMON
281
282 #define MAX_PENDING_ERQ 32 /* Max number of pending requests */
283
284 #define FLAG_NO_ERQ -2 /* No ERQ connected */
285 #define FLAG_ERQ_STOP -1 /* Severing connection */
286
287 static SOCKET_T erq_demon = FLAG_NO_ERQ;
288 /* Socket of the connection to the erq demon. */
289
290 static SOCKET_T erq_proto_demon = -1;
291 /* Socket to hold the connection to an aspiring new erq demon
292 * while the connection to the current one is being severed.
293 */
294
295 static char buf_from_erq[ERQ_MAX_REPLY];
296 /* Buffer for the data received from the erq */
297
298 static char * input_from_erq = &buf_from_erq[0];
299 /* Pointer to the first free byte in buf_from_erq. */
300
301 static unsigned long erq_pending_len = 0;
302 /* erq_pending_len is used by send_erq(), but needs
303 * to be cleared by stop_erq_demon().
304 */
305
306 typedef struct erq_callback_s {
307 svalue_t fun;
308 Bool string_arg;
309 } erq_callback_t;
310
311 static erq_callback_t pending_erq[MAX_PENDING_ERQ+1];
312 /* ERQ callback handles. The last one is reserved for callback-free
313 * requests.
314 * .fun is the callback closure, .string_arg is TRUE if the closure
315 * takes its data as a string instead of an array as argument.
316 *
317 * The free entries are organised in a singly linked list of
318 * T_INVALID .fun svalues, using the .fun.u.generic to point to the next
319 * free entry.
320 */
321
322 static erq_callback_t *free_erq;
323 /* The first free entry in the freelist in pending_erq[] */
324
325 /* The size of the IPTABLE depends on the number of users,
326 * and is at least 200.
327 */
328 #if MAX_PLAYERS > 700
329 # define IPSIZE MAX_PLAYERS
330 #else
331 # if MAX_PLAYERS > 100
332 # define IPSIZE (MAX_PLAYERS*2)
333 # else
334 # define IPSIZE 200
335 # endif
336 #endif
337
338 static struct ipentry {
339 struct in_addr addr; /* The address (only .s_addr is significant) */
340 string_t *name; /* tabled string with the hostname for <addr> */
341 } iptable[IPSIZE];
342 /* Cache of known names for given IP addresses.
343 * It is used as a ringbuffer, indexed by ipcur.
344 * TODO: Instead of a simple circular buffer, the lookup should be
345 * TODO:: hashed over the IP address. Worst case would still be O(IPSIZE),
346 * TODO:: but best case would be O(1).
347 * TODO: Allow unlimited numbers of entries, but give them a max lifetime
348 * TODO:: of a day. After that, even existing entries need to be
349 * TODO:: re-resolved. Maybe an additional size limit. (suggested by Coogan)
350 */
351
352 static int ipcur = 0;
353 /* Index of the next entry to use in the iptable[].
354 */
355
356 #endif /* ERQ_DEMON */
357
358 /*-------------------------------------------------------------------------*/
359
360 /* --- Communication sockets --- */
361
362 static SOCKET_T sos[MAXNUMPORTS];
363 /* The login sockets.
364 */
365
366 static SOCKET_T udp_s = -1;
367 /* The UDP socket */
368
369 /* --- Networking information --- */
370
371 static char host_name[MAXHOSTNAMELEN+1];
372 /* This computer's hostname, used for query_host_name() efun.
373 */
374
375 static struct in_addr host_ip_number;
376 /* This computer's numeric IP address only, used for
377 * the query_host_ip_number() efun.
378 */
379
380 static struct sockaddr_in host_ip_addr_template;
381 /* The template address of this computer. It is copied locally
382 * and augmented with varying port numbers to open the driver's ports.
383 */
384
385 char * domain_name = NULL;
386 /* This computer's domain name, as needed by lex.c::get_domainname().
387 */
388
389 static int min_nfds = 0;
390 /* The number of fds used by the driver's sockets (udp, erq, login).
391 * It is the number of the highest fd plus one.
392 */
393
394 /* --- Telnet handling --- */
395
396 Bool sending_telnet_command = MY_FALSE;
397 /* Mutex queried in add_message() to hide telnet commands
398 * from snoopers and shadows.
399 */
400
401 static void (*telopts_do [NTELOPTS])(int);
402 static void (*telopts_dont[NTELOPTS])(int);
403 static void (*telopts_will[NTELOPTS])(int);
404 static void (*telopts_wont[NTELOPTS])(int);
405
406 /* Tables with the telnet statemachine handlers.
407 */
408
409 enum telnet_states {
410 TS_DATA = 0,
411 TS_IAC,
412 TS_WILL,
413 TS_WONT,
414 TS_DO,
415 TS_DONT,
416 TS_SB,
417 TS_SB_IAC,
418 TS_READY,
419 TS_SYNCH,
420 TS_INVALID
421 };
422
423 /* Telnet states
424 */
425
TN_START_VALID(int x)426 static inline int TN_START_VALID(int x) {
427 return (x & ~TS_IAC) == TS_SB;
428 }
429
430
431 /* --- Misc --- */
432
433 static volatile Bool urgent_data = MY_FALSE;
434 /* Flag set when a SIGURG/SIGIO announces the arrival of
435 * OOB data.
436 */
437
438 static volatile mp_int urgent_data_time;
439 /* The backend::current_time when urgent_data was set last.
440 */
441
442 static interactive_t *first_player_for_flush = NULL;
443 /* First interactive user to flush. Marks the head of the list
444 * formed by interactive.{next,previous}_player_for_flush
445 */
446
447
448 /* Bitflags for interactive.do_close
449 *
450 * Putting PROTO_ERQ into do_close looks strange, but actually makes
451 * sense because some of the steps to be taken for both are the
452 * same.
453 */
454
455 #define FLAG_DO_CLOSE 0x1
456 #define FLAG_PROTO_ERQ 0x2
457
458
459 /*-------------------------------------------------------------------------*/
460
461 /* Outgoing connections in-progress */
462
463 typedef enum {
464 ocNotUsed /* Entry not used */
465 , ocUsed /* Entry holds pending connection */
466 , ocLoggingOn /* Entry is doing the LPC logon protocol.
467 * This value should not appear outside of
468 * check_for_out_connections(), if it does, it
469 * means that LPC logon threw an error.
470 */
471 } OutConnStatus;
472
473 struct OutConn {
474 struct sockaddr_in target; /* Address connected to (allocated) */
475 object_t * curr_obj; /* Associated object */
476 int socket; /* Socket on our side */
477 OutConnStatus status; /* Status of this entry */
478 } outconn[MAX_OUTCONN];
479
480 /*-------------------------------------------------------------------------*/
481
482 /* Forward declarations */
483
484 static void mccp_telnet_neg(int);
485
486 static void free_input_to(input_to_t *);
487 static void free_input_handler(input_t *);
488 static void telnet_neg(interactive_t *);
489 static void send_will(int);
490 static void send_wont(int);
491 static void send_do(int);
492 static void send_dont(int);
493 static void add_flush_entry(interactive_t *ip);
494 static void remove_flush_entry(interactive_t *ip);
495 static void clear_message_buf(interactive_t *ip);
496 static void new_player(object_t *receiver, SOCKET_T new_socket, struct sockaddr_in *addr, size_t len, int login_port);
497
498 #ifdef ERQ_DEMON
499
500 static long read_32(char *);
501 static Bool send_erq(int handle, int request, const char *arg, size_t arglen);
502 static void shutdown_erq_demon(void);
503 static void stop_erq_demon(Bool);
504 static string_t * lookup_ip_entry (struct in_addr addr, Bool useErq);
505 static void add_ip_entry(struct in_addr addr, const char *name);
506 #ifdef USE_IPV6
507 static void update_ip_entry(const char *oldname, const char *newname);
508 static int open_ipv6_conn(const char *hostname, const unsigned short int port, struct sockaddr_in *pTarget);
509 #endif
510
511 #endif /* ERQ_DEMON */
512
513 static INLINE ssize_t comm_send_buf(char *msg, size_t size, interactive_t *ip);
514
515 #ifdef USE_IPV6
516
517 /*-------------------------------------------------------------------------*/
518
519 /* Not every IPv6 supporting platform has all the defines (like AIX 4.3) */
520
521 #ifndef IPV6_ADDR_SCOPE_GLOBAL
522 # define IPV6_ADDR_SCOPE_GLOBAL 0x0e
523 #endif
524
525 #ifndef s6_addr8
526 # define s6_addr8 __u6_addr.__u6_addr8
527 #endif
528
529 #ifndef s6_addr16
530 # define s6_addr16 __u6_addr.__u6_addr16
531 #endif
532
533 #ifndef s6_addr32
534 # define s6_addr32 __u6_addr.__u6_addr32
535 #endif
536
CREATE_IPV6_MAPPED(struct in_addr * v6,uint32 v4)537 static inline void CREATE_IPV6_MAPPED(struct in_addr *v6, uint32 v4) {
538 v6->s6_addr32[0] = 0;
539 v6->s6_addr32[1] = 0;
540 v6->s6_addr32[2] = 0x0000ffff;
541 v6->s6_addr32[2] = 0xffff0000;
542 v6->s6_addr32[3] = v4;
543 }
544
545 /* These are the typical IPv6 structures - we use them transparently.
546 *
547 * --- arpa/inet.h ---
548 *
549 * struct in6_addr {
550 * union {
551 * u_int32_t u6_addr32[4];
552 * #ifdef notyet
553 * u_int64_t u6_addr64[2];
554 * #endif
555 * u_int16_t u6_addr16[8];
556 * u_int8_t u6_addr8[16];
557 * } u6_addr;
558 * };
559 * #define s6_addr32 u6_addr.u6_addr32
560 * #ifdef notyet
561 * #define s6_addr64 u6_addr.u6_addr64
562 * #endif
563 * #define s6_addr16 u6_addr.u6_addr16
564 * #define s6_addr8 u6_addr.u6_addr8
565 * #define s6_addr u6_addr.u6_addr8
566 *
567 * --- netinet/in.h ---
568 *
569 * struct sockaddr_in6 {
570 * u_char sin6_len;
571 * u_char sin6_family;
572 * u_int16_t sin6_port;
573 * u_int32_t sin6_flowinfo;
574 * struct in6_addr sin6_addr;
575 * };
576 *
577 */
578
579 /*-------------------------------------------------------------------------*/
580 static char *
inet6_ntoa(struct in6_addr in)581 inet6_ntoa (struct in6_addr in)
582
583 /* Convert the ipv6 address <in> into a string and return it.
584 * Note: the string is stored in a local buffer.
585 */
586
587 {
588 static char str[INET6_ADDRSTRLEN+1];
589
590 if (NULL == inet_ntop(AF_INET6, &in, str, INET6_ADDRSTRLEN))
591 {
592 perror("inet_ntop");
593 }
594 return str;
595 } /* inet6_ntoa() */
596
597 /*-------------------------------------------------------------------------*/
598 static struct in6_addr
inet6_addr(const char * to_host)599 inet6_addr (const char *to_host)
600
601 /* Convert the name <to_host> into a ipv6 address and return it.
602 */
603
604 {
605 struct in6_addr addr;
606
607 inet_pton(AF_INET6, to_host, &addr);
608 return addr;
609 } /* inet6_addr() */
610
611 #endif /* USE_IPV6 */
612
613 /*-------------------------------------------------------------------------*/
614 static char *
decode_noecho(char noecho)615 decode_noecho (char noecho)
616
617 /* Decode the <noecho> flag byte into a string.
618 * Result is a pointer to a static buffer.
619 */
620
621 {
622 static char buf[100];
623 strcpy(buf, "(");
624 if (noecho & NOECHO_REQ) strcat(buf, "NOECHO_REQ, ");
625 if (noecho & CHARMODE_REQ) strcat(buf, "CHARMODE_REQ, ");
626 if (noecho & NOECHO) strcat(buf, "NOECHO, ");
627 if (noecho & CHARMODE) strcat(buf, "CHARMODE, ");
628 if (noecho & NOECHO_ACK) strcat(buf, "NOECHO_ACK, ");
629 if (noecho & CHARMODE_ACK) strcat(buf, "CHARMODE_ACK, ");
630 #ifdef SAVE_NOECHO
631 if (noecho & NOECHO_DELAYED) strcat(buf, "NOECHO_DELAYED, ");
632 #endif
633 if (noecho & NOECHO_STALE) strcat(buf, "NOECHO_STALE, ");
634 if (noecho & IGNORE_BANG) strcat(buf, "IGNORE_BANG");
635 strcat(buf, ")");
636
637 return buf;
638 } /* decode_noecho() */
639
640 /*-------------------------------------------------------------------------*/
641 static void
dump_bytes(void * data,size_t length,int indent)642 dump_bytes (void * data, size_t length, int indent)
643
644 /* Write the datablock starting at <data> of size <length> to stderr.
645 * If it spans more than one line, indent the following lines by <indent>.
646 */
647
648 {
649 int cur_indent = 0;
650 unsigned char * datap = (unsigned char *)data;
651
652 while (length > 0)
653 {
654 size_t count;
655
656 if (cur_indent)
657 fprintf(stderr, "%*.*s", cur_indent, cur_indent, " ");
658 else
659 cur_indent = indent;
660 fprintf(stderr, " %p:", datap);
661
662 for (count = 0; count < 16 && length > 0; ++count, --length, ++datap)
663 {
664 fprintf(stderr, " %02x", *datap);
665 }
666 putc('\n', stderr);
667 }
668 } /* dump_bytes() */
669
670 /*-------------------------------------------------------------------------*/
671 static void comm_fatal (interactive_t *ip, char *fmt, ...)
672 FORMATDEBUG(printf,2,3) ;
673 static void
comm_fatal(interactive_t * ip,char * fmt,...)674 comm_fatal (interactive_t *ip, char *fmt, ...)
675
676 /* The telnet code ran into a fatal error.
677 * Dump the data from the current interactive structure and disconnect
678 * the user (we have to assume that the interactive structure is
679 * irrecoverably hosed).
680 * TODO: Make similar functions comm_error(), comm_perror() which prefix
681 * TODO:: the error message with the ip %p and obj name.
682 */
683
684 {
685 va_list va;
686 static Bool in_fatal = MY_FALSE;
687 char * ts;
688 char * msg = "\r\n=== Internal communications error in mud driver.\r\n"
689 "=== Please log back in and inform the administration.\r\n"
690 "\r\n";
691
692 /* Prevent double fatal. */
693 if (in_fatal)
694 fatal("Recursive call to comm_fatal().");
695 in_fatal = MY_TRUE;
696 ts = time_stamp();
697
698 /* Print the error message */
699
700 va_start(va, fmt);
701
702 fflush(stdout);
703 fprintf(stderr, "%s ", ts);
704 vfprintf(stderr, fmt, va);
705 fflush(stderr);
706 if (current_object)
707 fprintf(stderr, "%s Current object was %s\n"
708 , ts, current_object->name
709 ? get_txt(current_object->name) : "<null>");
710 debug_message("%s ", ts);
711 vdebug_message(fmt, va);
712 if (current_object)
713 debug_message("%s Current object was %s\n"
714 , ts, current_object->name
715 ? get_txt(current_object->name) : "<null>");
716 debug_message("%s Dump of the call chain:\n", ts);
717 (void)dump_trace(MY_TRUE, NULL); fflush(stdout);
718
719 va_end(va);
720
721 /* Dump the interactive structure */
722
723 fprintf(stderr, "--- Dump of current interactive structure (%p..%p) --- \n"
724 , ip, ip + sizeof(*ip) - 1);
725 fprintf(stderr, " .socket: %d\n", ip->socket);
726 fprintf(stderr, " .ob: %p", ip->ob);
727 if (ip->ob) fprintf(stderr, " (%s)", get_txt(ip->ob->name));
728 putc('\n', stderr);
729 fprintf(stderr, " .input_handler: %p\n", ip->input_handler);
730 fprintf(stderr, " .modify_command: %p", ip->modify_command);
731 if (ip->modify_command) fprintf(stderr, " (%s)", get_txt(ip->modify_command->name));
732 putc('\n', stderr);
733 fprintf(stderr, " .prompt: ");
734 dump_bytes(&(ip->prompt), sizeof(ip->prompt), 21);
735 fprintf(stderr, " .addr: ");
736 dump_bytes(&(ip->addr), sizeof(ip->addr), 21);
737 fprintf(stderr, " .closing: %02hhx\n", (unsigned char)ip->closing);
738 fprintf(stderr, " .tn_enabled: %02hhx\n", (unsigned char)ip->tn_enabled);
739 fprintf(stderr, " .do_close: %02hhx", (unsigned char)ip->do_close);
740 if (ip->do_close & (FLAG_DO_CLOSE|FLAG_PROTO_ERQ)) fprintf(stderr, " (");
741 if (ip->do_close & FLAG_DO_CLOSE) fprintf(stderr, "DO_CLOSE");
742 if (ip->do_close & (FLAG_DO_CLOSE|FLAG_PROTO_ERQ)) fprintf(stderr, ", ");
743 if (ip->do_close & FLAG_PROTO_ERQ) fprintf(stderr, "PROTO_ERQ");
744 if (ip->do_close & (FLAG_DO_CLOSE|FLAG_PROTO_ERQ)) fprintf(stderr, ")");
745 putc('\n', stderr);
746 fprintf(stderr, " .noecho: %02hhx", (unsigned char)ip->noecho);
747 fprintf(stderr, " %s\n", decode_noecho(ip->noecho));
748 fprintf(stderr, " .tn_state: %hhd", ip->tn_state);
749 switch(ip->tn_state) {
750 case TS_DATA: fprintf(stderr, " (TS_DATA)\n"); break;
751 case TS_IAC: fprintf(stderr, " (TS_IAC)\n"); break;
752 case TS_WILL: fprintf(stderr, " (TS_WILL)\n"); break;
753 case TS_WONT: fprintf(stderr, " (TS_WONT)\n"); break;
754 case TS_DO: fprintf(stderr, " (TS_DO)\n"); break;
755 case TS_DONT: fprintf(stderr, " (TS_DONT)\n"); break;
756 case TS_SB: fprintf(stderr, " (TS_SB)\n"); break;
757 case TS_SB_IAC: fprintf(stderr, " (TS_SB_IAC)\n"); break;
758 case TS_READY: fprintf(stderr, " (TS_READY)\n"); break;
759 case TS_SYNCH: fprintf(stderr, " (TS_SYNCH)\n"); break;
760 case TS_INVALID: fprintf(stderr, " (TS_INVALID)\n"); break;
761 default: putc('\n', stderr);
762 }
763 fprintf(stderr, " .save_tn_state: %hhd", ip->save_tn_state);
764 switch(ip->save_tn_state) {
765 case TS_DATA: fprintf(stderr, " (TS_DATA)\n"); break;
766 case TS_IAC: fprintf(stderr, " (TS_IAC)\n"); break;
767 case TS_WILL: fprintf(stderr, " (TS_WILL)\n"); break;
768 case TS_WONT: fprintf(stderr, " (TS_WONT)\n"); break;
769 case TS_DO: fprintf(stderr, " (TS_DO)\n"); break;
770 case TS_DONT: fprintf(stderr, " (TS_DONT)\n"); break;
771 case TS_SB: fprintf(stderr, " (TS_SB)\n"); break;
772 case TS_SB_IAC: fprintf(stderr, " (TS_SB_IAC)\n"); break;
773 case TS_READY: fprintf(stderr, " (TS_READY)\n"); break;
774 case TS_SYNCH: fprintf(stderr, " (TS_SYNCH)\n"); break;
775 case TS_INVALID: fprintf(stderr, " (TS_INVALID)\n"); break;
776 default: putc('\n', stderr);
777 }
778 fprintf(stderr, " .supress_go_ahead: %02hhx\n", (unsigned char)ip->supress_go_ahead);
779 fprintf(stderr, " .text_end: %hd (%p)\n", ip->text_end, ip->text+ip->text_end);
780 fprintf(stderr, " .command_start: %hd (%p)\n", ip->command_start, ip->text+ip->command_start);
781 fprintf(stderr, " .command_end: %hd (%p)\n", ip->command_end, ip->text+ip->command_end);
782 fprintf(stderr, " .tn_start: %hd (%p)\n", ip->tn_start, ip->text+ip->tn_start);
783 fprintf(stderr, " .tn_end: %hd (%p)\n", ip->tn_end, ip->text+ip->tn_end);
784 fprintf(stderr, " .chars_ready: %"PRId32"\n",ip->chars_ready);
785 fprintf(stderr, " .snoop_on: %p", ip->snoop_on);
786 if (ip->snoop_on && ip->snoop_on->ob) fprintf(stderr, " (%s)", get_txt(ip->snoop_on->ob->name));
787 putc('\n', stderr);
788 fprintf(stderr, " .snoop_by: %p", ip->snoop_by);
789 if (ip->snoop_by) fprintf(stderr, " (%s)", get_txt(ip->snoop_by->name));
790 putc('\n', stderr);
791 fprintf(stderr, " .last_time: %"PRIdMPINT"\n", ip->last_time);
792 fprintf(stderr, " .numCmds: %ld\n", ip->numCmds);
793 fprintf(stderr, " .maxNumCmds: %ld\n", ip->maxNumCmds);
794 fprintf(stderr, " .trace_level: %d\n", ip->trace_level);
795 fprintf(stderr, " .trace_prefix: %p", ip->trace_prefix);
796 if (ip->trace_prefix) fprintf(stderr, " '%s'", get_txt(ip->trace_prefix));
797 putc('\n', stderr);
798 fprintf(stderr, " .message_length: %d (%p)\n", ip->message_length, ip->message_buf+ip->message_length);
799 fprintf(stderr, " .next_for_flush: %p", ip->next_player_for_flush);
800 if (ip->next_player_for_flush) fprintf(stderr, " (%s)", get_txt(ip->next_player_for_flush->ob->name));
801 putc('\n', stderr);
802 fprintf(stderr, " .prev_for_flush: %p", ip->previous_player_for_flush);
803 if (ip->previous_player_for_flush) fprintf(stderr, " (%s)", get_txt(ip->previous_player_for_flush->ob->name));
804 putc('\n', stderr);
805 fprintf(stderr, " .access_class: %ld\n", ip->access_class);
806 fprintf(stderr, " .charset: ");
807 dump_bytes(&(ip->charset), sizeof(ip->charset), 21);
808 fprintf(stderr, " .combine_cset: ");
809 dump_bytes(&(ip->combine_cset), sizeof(ip->combine_cset), 21);
810 fprintf(stderr, " .quote_iac: %02hhx\n", (unsigned char)ip->quote_iac);
811 fprintf(stderr, " .catch_tell_activ: %02hhx\n", (unsigned char)ip->catch_tell_activ);
812 fprintf(stderr, " .gobble_char: %02hhx\n", (unsigned char)ip->gobble_char);
813 fprintf(stderr, " .ts_data: %02hhx\n", (unsigned char)ip->ts_data);
814 fprintf(stderr, " .text: ");
815 dump_bytes(&(ip->text), sizeof(ip->text), 21);
816 fprintf(stderr, " .message_buf: ");
817 dump_bytes(&(ip->message_buf), sizeof(ip->message_buf), 21);
818 fprintf(stderr, "------\n");
819
820 /* Disconnect the user */
821 comm_send_buf(msg, strlen(msg), ip);
822 remove_interactive(ip->ob, MY_TRUE);
823
824 /* Unset mutex */
825 in_fatal = MY_FALSE;
826 } /* comm_fatal() */
827
828 /*-------------------------------------------------------------------------*/
829 static void
set_socket_nonblocking(SOCKET_T new_socket)830 set_socket_nonblocking (SOCKET_T new_socket)
831
832 /* Set the <new_socket> into non-blocking mode.
833 * Abort on error.
834 */
835
836 {
837 int tmp;
838
839 tmp = 1;
840
841 # ifdef USE_IOCTL_FIONBIO
842 if (socket_ioctl(new_socket, FIONBIO, &tmp) == -1) {
843 perror("ioctl socket FIONBIO");
844 abort();
845 }
846 # else /* !USE_IOCTL_FIONBIO */
847 # ifdef USE_FCNTL_O_NDELAY
848 if (fcntl(new_socket, F_SETFL, O_NDELAY) == -1) {
849 # else
850 if (fcntl(new_socket, F_SETFL, FNDELAY) == -1) {
851 # endif
852 perror("fcntl socket FNDELAY");
853 abort();
854 }
855 # endif /* !USE_IOCTL_FIONBIO */
856
857 } /* set_socket_nonblocking() */
858
859 /*-------------------------------------------------------------------------*/
860 static void
861 set_close_on_exec (SOCKET_T new_socket)
862
863 /* Set that <new_socket> is closed when the driver performs an exec()
864 * (i.e. when starting the ERQ).
865 * Failure is acceptable as this is just a nicety.
866 */
867
868 {
869 #ifdef HAVE_FCNTL
870 fcntl(new_socket, F_SETFD, 1L);
871 #endif
872 } /* set_close_on_exec() */
873
874 /*-------------------------------------------------------------------------*/
875 static void
876 set_socket_own (SOCKET_T new_socket)
877
878 /* Enable OOB communication on <new_socket>: the driver is set to
879 * receive SIGIO and SIGURG signals, and OOBINLINE is enabled.
880 * Failure is acceptable as both facilities are not available everywhere.
881 */
882
883 {
884 #if defined(F_SETOWN) && defined(USE_FCNTL_SETOWN)
885 if (0 > fcntl(new_socket, F_SETOWN, getpid()))
886 {
887 perror("fcntl SETOWN");
888 }
889 #endif
890 #if defined(SO_OOBINLINE) && defined(USE_OOBINLINE)
891 {
892 int on = 1;
893 if (0 > setsockopt(new_socket, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof on))
894 {
895 perror("setsockopt SO_OOBINLINE");
896 }
897 }
898 #endif
899 new_socket = 0; /* Prevent 'not used' warning */
900 } /* set_socket_own() */
901
902 /*-------------------------------------------------------------------------*/
903 void
904 initialize_host_name (const char *hname)
905
906 /* This function is called at an early stage of the driver startup in order
907 * to initialise the global host_name with a useful value (specifically so
908 * that we can open the debug.log file).
909 * If <hname> is given, the hostname is parsed from the string, otherwise it
910 * is queried from the system.
911 *
912 * The value set in this function will later be overwritten by the
913 * call to initialize_host_ip_number().
914 *
915 * exit() on failure.
916 */
917
918 {
919 char *domain;
920
921 /* Get the (possibly qualified) hostname */
922 if (hname != NULL)
923 {
924 if (strlen(hname) > MAXHOSTNAMELEN)
925 {
926 fprintf(stderr, "%s Given hostname '%s' too long.\n"
927 , time_stamp(), hname);
928 exit(1);
929 }
930 else
931 strcpy(host_name, hname);
932 }
933 else
934 {
935 if (gethostname(host_name, sizeof host_name) == -1) {
936 herror("gethostname");
937 exit(1);
938 }
939 }
940
941 /* Cut off the domain name part of the hostname, if any.
942 */
943 domain = strchr(host_name, '.');
944 if (domain)
945 *domain = '\0';
946 } /* initialize_host_name() */
947
948 /*-------------------------------------------------------------------------*/
949 void
950 initialize_host_ip_number (const char *hname, const char * haddr)
951
952 /* Initialise the globals host_ip_number and host_ip_addr_template.
953 * If <hname> or <haddr> are given, the hostname/hostaddr are parsed
954 * from the strings, otherwise they are queried from the system.
955 *
956 * Open the UDP port if requested so that it can be used in inaugurate_master().
957 * exit() on failure.
958 */
959
960 {
961 char *domain;
962 length_t tmp;
963
964 /* Get the (possibly qualified) hostname */
965 if (hname != NULL)
966 {
967 if (strlen(hname) > MAXHOSTNAMELEN)
968 {
969 fprintf(stderr, "%s Given hostname '%s' too long.\n"
970 , time_stamp(), hname);
971 exit(1);
972 }
973 else
974 strcpy(host_name, hname);
975 }
976 else
977 {
978 if (gethostname(host_name, sizeof host_name) == -1) {
979 herror("gethostname");
980 exit(1);
981 }
982 }
983
984 /* Get the host address */
985 memset(&host_ip_addr_template, 0, sizeof host_ip_addr_template);
986 if (haddr != NULL)
987 {
988 #ifndef USE_IPV6
989 host_ip_number.s_addr = inet_addr(haddr);
990 host_ip_addr_template.sin_family = AF_INET;
991 host_ip_addr_template.sin_addr = host_ip_number;
992 #else
993 host_ip_number = inet6_addr(haddr);
994 host_ip_addr_template.sin_family = AF_INET6;
995 host_ip_addr_template.sin_addr = host_ip_number;
996 #endif
997
998 /* Find the domain part of the hostname */
999 domain = strchr(host_name, '.');
1000 }
1001 else
1002 {
1003 struct hostent *hp;
1004
1005 hp = gethostbyname(host_name);
1006 if (!hp) {
1007 fprintf(stderr, "%s gethostbyname: unknown host '%s'.\n"
1008 , time_stamp(), host_name);
1009 exit(1);
1010 }
1011 memcpy(&host_ip_addr_template.sin_addr, hp->h_addr, (size_t)hp->h_length);
1012 host_ip_addr_template.sin_family = (unsigned short)hp->h_addrtype;
1013 host_ip_number = host_ip_addr_template.sin_addr;
1014
1015 /* Now set the template to the proper _ANY value */
1016 memset(&host_ip_addr_template.sin_addr, 0, sizeof(host_ip_addr_template.sin_addr));
1017 #ifndef USE_IPV6
1018 host_ip_addr_template.sin_addr.s_addr = INADDR_ANY;
1019 host_ip_addr_template.sin_family = AF_INET;
1020 #else
1021 host_ip_addr_template.sin_addr = in6addr_any;
1022 host_ip_addr_template.sin_family = AF_INET6;
1023 #endif
1024
1025 /* Find the domain part of the hostname */
1026 if (hname == NULL)
1027 domain = strchr(hp->h_name, '.');
1028 else
1029 domain = strchr(host_name, '.');
1030 }
1031
1032 #ifndef USE_IPV6
1033 printf("%s Hostname '%s' address '%s'\n"
1034 , time_stamp(), host_name, inet_ntoa(host_ip_number));
1035 debug_message("%s Hostname '%s' address '%s'\n"
1036 , time_stamp(), host_name, inet_ntoa(host_ip_number));
1037 #else
1038 printf("%s Hostname '%s' address '%s'\n"
1039 , time_stamp(), host_name, inet6_ntoa(host_ip_number));
1040 debug_message("%s Hostname '%s' address '%s'\n"
1041 , time_stamp(), host_name, inet6_ntoa(host_ip_number));
1042 #endif
1043
1044 /* Put the domain name part of the hostname into domain_name, then
1045 * strip it off the host_name[] (as only query_host_name() is going
1046 * to need it).
1047 * Note that domain might not point into host_name[] here, so we
1048 * can't just stomp '\0' in there.
1049 */
1050 if (domain)
1051 {
1052 domain_name = strdup(domain+1);
1053 }
1054 else
1055 domain_name = strdup("unknown");
1056
1057 domain = strchr(host_name, '.');
1058 if (domain)
1059 *domain = '\0';
1060
1061 /* Initialize udp at an early stage so that the master object can use
1062 * it in inaugurate_master() , and the port number is known.
1063 */
1064 if (udp_port != -1)
1065 {
1066 struct sockaddr_in host_ip_addr;
1067
1068 memcpy(&host_ip_addr, &host_ip_addr_template, sizeof(host_ip_addr));
1069
1070 host_ip_addr.sin_port = htons((u_short)udp_port);
1071 debug_message("%s UDP recv-socket requested for port: %d\n"
1072 , time_stamp(), udp_port);
1073 udp_s = socket(host_ip_addr.sin_family, SOCK_DGRAM, 0);
1074 if (udp_s == -1)
1075 {
1076 perror("socket(udp_socket)");
1077 exit(1);
1078 }
1079 tmp = 1;
1080 if (setsockopt (udp_s, SOL_SOCKET, SO_REUSEADDR,
1081 (char *) &tmp, sizeof (tmp)) < 0)
1082 {
1083 perror ("setsockopt(udp_s, SO_REUSEADDR)");
1084 exit(1);
1085 }
1086
1087 /* Bind the UDP socket to an address.
1088 * First, try the given port number, if that one is in use
1089 * already, let bind() select one. If that one is in use, too,
1090 * close the socket again and pretend that we never had one.
1091 * Other errors abort the driver.
1092 */
1093 for(;;) {
1094 if (-1 == bind(udp_s, (struct sockaddr *)&host_ip_addr
1095 , sizeof(host_ip_addr)))
1096 {
1097 if (errno == EADDRINUSE) {
1098 fprintf(stderr, "%s UDP port %d already bound!\n"
1099 , time_stamp(), udp_port);
1100 debug_message("%s UDP port %d already bound!\n"
1101 , time_stamp(), udp_port);
1102 if (host_ip_addr.sin_port) {
1103 host_ip_addr.sin_port = 0;
1104 continue;
1105 }
1106 close(udp_s);
1107 udp_s = -1;
1108 } else {
1109 perror("udp-bind");
1110 exit(1);
1111 }
1112 }
1113 break;
1114 }
1115 }
1116
1117 /* If we got the UDP socket, get query it's real address and
1118 * initialise it.
1119 */
1120 if (udp_s >= 0) {
1121 struct sockaddr_in host_ip_addr;
1122
1123 tmp = sizeof(host_ip_addr);
1124 if (!getsockname(udp_s, (struct sockaddr *)&host_ip_addr, &tmp))
1125 {
1126 int oldport = udp_port;
1127
1128 udp_port = ntohs(host_ip_addr.sin_port);
1129 if (oldport != udp_port)
1130 debug_message("%s UDP recv-socket on port: %d\n"
1131 , time_stamp(), udp_port);
1132 }
1133 set_socket_nonblocking(udp_s);
1134 set_close_on_exec(udp_s);
1135 if (socket_number(udp_s) >= min_nfds)
1136 min_nfds = socket_number(udp_s)+1;
1137 }
1138
1139 } /* initialize_host_ip_number() */
1140
1141
1142 /*-------------------------------------------------------------------------*/
1143 static void
1144 urgent_data_handler (int signo)
1145
1146 /* Signal handler for SIGURG/SIGIO: set the urgent_data flag and
1147 * note the time.
1148 */
1149
1150 {
1151 if (d_flag)
1152 write(2, "received urgent data\n", 21);
1153 urgent_data = MY_TRUE;
1154 urgent_data_time = current_time;
1155 }
1156
1157 /*-------------------------------------------------------------------------*/
1158 void
1159 prepare_ipc(void)
1160
1161 /* Open all login sockets on driver startup, exit() on a failure.
1162 */
1163
1164 {
1165 length_t tmp;
1166 int i;
1167 struct sigaction sa; // for installing the signal handlers
1168
1169 #ifdef ERQ_DEMON
1170 /* Initialize the IP name lookup table */
1171 memset(iptable, 0, sizeof(iptable));
1172 #endif
1173
1174 for (i = 0; i < MAX_OUTCONN; i++)
1175 outconn[i].status = ocNotUsed;
1176
1177 /* Initialize the telnet machine unless mudlib_telopts() already
1178 * did that.
1179 */
1180 if (!telopts_do[0])
1181 init_telopts();
1182
1183 /* Loop over all given port numbers.
1184 * Remember: positive number are actual port numbers to be opened,
1185 * negative numbers are the fd numbers of already existing sockets.
1186 */
1187 for (i = 0; i < numports; i++)
1188 {
1189 struct sockaddr_in host_ip_addr;
1190
1191 memcpy(&host_ip_addr, &host_ip_addr_template, sizeof(host_ip_addr));
1192
1193 if (port_numbers[i] > 0)
1194 {
1195 /* Real port number */
1196
1197 host_ip_addr.sin_port = htons((u_short)port_numbers[i]);
1198 sos[i] = socket(host_ip_addr.sin_family, SOCK_STREAM, 0);
1199 if ((int)sos[i] == -1) {
1200 perror("socket");
1201 exit(1);
1202 }
1203 tmp = 1;
1204 if (setsockopt(sos[i], SOL_SOCKET, SO_REUSEADDR
1205 , (char *) &tmp, sizeof (tmp)) < 0) {
1206 perror ("setsockopt");
1207 exit (1);
1208 }
1209 if (bind(sos[i], (struct sockaddr *)&host_ip_addr, sizeof host_ip_addr) == -1) {
1210 if (errno == EADDRINUSE) {
1211 fprintf(stderr, "%s Port %d already bound!\n"
1212 , time_stamp(), port_numbers[i]);
1213 debug_message("%s Port %d already bound!\n"
1214 , time_stamp(), port_numbers[i]);
1215 exit(errno);
1216 } else {
1217 perror("bind");
1218 exit(1);
1219 }
1220 }
1221 }
1222 else {
1223
1224 /* Existing socket */
1225
1226 sos[i] = -port_numbers[i];
1227 tmp = sizeof(host_ip_addr);
1228 if (!getsockname(sos[i], (struct sockaddr *)&host_ip_addr, &tmp))
1229 port_numbers[i] = ntohs(host_ip_addr.sin_port);
1230 }
1231
1232 /* Initialise the socket */
1233 if (listen(sos[i], 5) == -1) {
1234 perror("listen");
1235 exit(1);
1236 }
1237 set_socket_nonblocking(sos[i]);
1238 set_close_on_exec(sos[i]);
1239
1240 if (socket_number(sos[i]) >= min_nfds)
1241 min_nfds = socket_number(sos[i])+1;
1242 } /* for(i = 0..numports) */
1243
1244 // install some signal handlers
1245 sigemptyset(&sa.sa_mask);
1246 sa.sa_flags = SA_RESTART; // restart syscalls after handling a signal
1247
1248 /* We ignore SIGPIPE and handle the errors on write/send ourself */
1249 sa.sa_handler = SIG_IGN;
1250 if (sigaction(SIGPIPE, &sa, NULL) == -1)
1251 perror("Unable to install signal handler for SIGPIPE"); // uhoh. SIGPIPE terminates...
1252
1253 sa.sa_handler = urgent_data_handler;
1254 if (sigaction(SIGURG, &sa, NULL) == -1)
1255 perror("Unable to install signal handler for SIGURG");
1256 if (sigaction(SIGIO, &sa, NULL) == -1)
1257 perror("Unable to install signal handler for SIGIO"); // uhoh. SIGIO terminates...
1258
1259 } /* prepare_ipc() */
1260
1261 /*-------------------------------------------------------------------------*/
1262 void
1263 ipc_remove (void)
1264
1265 /* Called when the driver is shutting down, this function closes all
1266 * open sockets.
1267 */
1268
1269 {
1270 int i;
1271
1272 printf("%s Shutting down ipc...\n", time_stamp());
1273 for (i = 0; i < numports; i++)
1274 socket_close(sos[i]);
1275
1276 if (udp_s >= 0)
1277 socket_close(udp_s);
1278
1279 #ifdef ERQ_DEMON
1280 shutdown_erq_demon();
1281 #endif
1282
1283 } /* ipc_remove() */
1284
1285 /*-------------------------------------------------------------------------*/
1286 static INLINE ssize_t
1287 comm_send_buf (char *msg, size_t size, interactive_t *ip)
1288
1289 /* Low level send routine, just tries to send the data without buffering.
1290 A return value -1 indicates a total failure (i.e. the connection should
1291 be dropped), otherwise the amount of data sent (even if it's 0).
1292 */
1293 {
1294 int retries; /* Number of retries left when sending data */
1295 ssize_t n; /* Bytes that have been sent */
1296
1297 for (retries = 6;;)
1298 {
1299 #ifdef USE_TLS
1300 if ((n = (ip->tls_status == TLS_INACTIVE ?
1301 (int)socket_write(ip->socket, msg, size):
1302 (int)tls_write(ip, msg, size))) != -1)
1303 #else
1304 if ((n = (int)socket_write(ip->socket, msg, size)) != -1)
1305 #endif
1306 {
1307 break;
1308 }
1309
1310 switch (errno)
1311 {
1312
1313 case EINTR:
1314 if (--retries)
1315 continue;
1316 n = 0;
1317 break;
1318
1319 case EWOULDBLOCK:
1320 n = 0;
1321 break;
1322
1323 case EMSGSIZE:
1324 fprintf(stderr, "%s comm: write EMSGSIZE.\n", time_stamp());
1325 break;
1326
1327 case EINVAL:
1328 fprintf(stderr, "%s comm: write EINVAL.\n", time_stamp());
1329 break;
1330
1331 case ENETUNREACH:
1332 fprintf(stderr, "%s comm: write ENETUNREACH.\n", time_stamp());
1333 break;
1334
1335 case EHOSTUNREACH:
1336 fprintf(stderr, "%s comm: write EHOSTUNREACH.\n", time_stamp());
1337 break;
1338
1339 case EPIPE:
1340 fprintf(stderr, "%s comm: write EPIPE detected\n", time_stamp());
1341 break;
1342
1343 case ECONNRESET:
1344 fprintf(stderr, "%s comm: write ECONNRESET detected\n", time_stamp());
1345 break;
1346
1347 default:
1348 {
1349 int e = errno;
1350 fprintf(stderr, "%s comm: write: unknown errno %d (%s)\n"
1351 , time_stamp(), e, strerror(e));
1352 }
1353 }
1354
1355 if (n == 0) // don't close for EWOULDBLOCK/EINTR
1356 return 0;
1357
1358 ip->do_close = FLAG_DO_CLOSE;
1359 return -1;
1360
1361 } /* for (retries) */
1362
1363 #ifdef COMM_STAT
1364 inet_packets++;
1365 inet_volume += n;
1366 #endif
1367
1368 return n;
1369 } /* comm_send_buf() */
1370
1371 /*-------------------------------------------------------------------------*/
1372 Bool
1373 comm_socket_write (char *msg, size_t size, interactive_t *ip, write_buffer_flag_t flags)
1374
1375 /* Stand in for socket_write(): take the data to be written, compress and
1376 * encrypt them if needed and send them to <ip>. If no data can be send
1377 * right now append them to the buffer. Returns false if no more data
1378 * is accepted at this time (messages are discarded or the connection
1379 * was dropped).
1380 */
1381
1382 {
1383 struct write_buffer_s *b;
1384 char *buf;
1385 size_t length;
1386
1387 if (size == 0)
1388 return MY_TRUE;
1389
1390 #ifdef USE_MCCP
1391 /* We cannot discard already compressed packets,
1392 * because the zlib will generate a checksum
1393 * over all bytes. So we have to check before
1394 * compressing the message whether we can send
1395 * or put them in the write buffer.
1396 *
1397 * To provide a consistent behavior we do this
1398 * also for uncompressed connections.
1399 */
1400 #endif
1401
1402 if (!(flags & WB_NONDISCARDABLE) && ip->write_first)
1403 {
1404 p_int max_size;
1405
1406 max_size = ip->write_max_size;
1407 if (max_size == -2)
1408 max_size = write_buffer_max_size;
1409
1410 if (max_size >= 0 && ip->write_size >= (p_uint) max_size)
1411 {
1412 /* Buffer overflow. */
1413 if (ip->msg_discarded != DM_NONE)
1414 return MY_FALSE; /* Message will be or was sent. */
1415
1416 /* Notify the master about it. */
1417 ip->msg_discarded = DM_SEND_INFO;
1418 add_flush_entry(ip);
1419
1420 return MY_FALSE;
1421 }
1422 }
1423
1424 #ifdef USE_MCCP
1425 if (ip->out_compress)
1426 {
1427 int status;
1428
1429 ip->out_compress->next_in = (unsigned char *) msg;
1430 ip->out_compress->avail_in = size;
1431
1432 ip->out_compress->next_out = ip->out_compress_buf;
1433 ip->out_compress->avail_out = COMPRESS_BUF_SIZE;
1434
1435 status = deflate(ip->out_compress, Z_SYNC_FLUSH);
1436
1437 if (status != Z_OK)
1438 {
1439 fprintf(stderr, "%s comm: MCCP compression error: %d\n"
1440 , time_stamp(), status);
1441 return MY_FALSE;
1442 }
1443
1444 /* ok.. perhaps i should take care that all data in message_buf
1445 * is compressed, but i guess there is no chance that 1024 byte
1446 * compressed won't fit into the 8192 byte buffer
1447 */
1448
1449 length = ip->out_compress->next_out - ip->out_compress_buf;
1450 buf = (char *) ip->out_compress_buf;
1451 }
1452 else
1453 #endif /* USE_MCCP */
1454 {
1455 buf = msg;
1456 length = size;
1457 }
1458
1459 /* now sending the buffer... */
1460 if (ip->write_first == NULL)
1461 {
1462 /* Try writing to the socket first. */
1463 ssize_t n = comm_send_buf(buf, length, ip);
1464
1465 if (n == -1)
1466 return MY_FALSE;
1467 else if (n == length)
1468 {
1469 /* We're done. */
1470 return MY_TRUE;
1471 }
1472 else if (n > 0)
1473 {
1474 buf += n;
1475 length -= n;
1476 }
1477 }
1478
1479 /* We have to enqueue the message. */
1480
1481 b = xalloc(sizeof(struct write_buffer_s) + length - 1);
1482 if (!b)
1483 outofmem(sizeof(struct write_buffer_s) + length - 1, "comm_socket_write()");
1484
1485 b->length = length;
1486 b->pos = 0;
1487 b->flags = flags;
1488 b->next = NULL;
1489 memcpy(b->buffer, buf, length);
1490
1491 /* Chain in the new buffer */
1492 if (ip->write_first)
1493 ip->write_last = ip->write_last->next = b;
1494 else
1495 ip->write_last = ip->write_first = b;
1496
1497 ip->write_size += length;
1498 ip->msg_discarded = DM_NONE;
1499
1500 return MY_TRUE;
1501 } /* comm_socket_write() */
1502
1503 /*-------------------------------------------------------------------------*/
1504 static void
1505 comm_write_pending (interactive_t * ip)
1506
1507 /* Send as much from the write buffer of <ip> as possible.
1508 */
1509
1510 {
1511 while (ip->write_first != NULL)
1512 {
1513 struct write_buffer_s *buf;
1514 ssize_t n;
1515
1516 buf = ip->write_first;
1517 n = comm_send_buf(buf->buffer + buf->pos, buf->length - buf->pos, ip);
1518
1519 if (n == -1)
1520 return;
1521
1522 buf->pos += n;
1523 if (buf->pos < buf->length)
1524 return;
1525
1526 ip->write_first = buf->next;
1527 ip->write_size -= buf->length;
1528 xfree(buf);
1529 }
1530 } /* comm_write_pending() */
1531
1532 /*-------------------------------------------------------------------------*/
1533 static void
1534 add_discarded_message (interactive_t *ip)
1535
1536 /* Calls the H_MSG_DISCARDED driver hook and adds the
1537 * message to the write buffer of <ip>. <ip> is removed
1538 * from the list of dirty interactives if it's clean afterwards.
1539 */
1540 {
1541 string_t *discarded_msg;
1542
1543 if (driver_hook[H_MSG_DISCARDED].type == T_CLOSURE)
1544 {
1545 if (driver_hook[H_MSG_DISCARDED].x.closure_type == CLOSURE_LAMBDA)
1546 {
1547 free_object(driver_hook[H_MSG_DISCARDED].u.lambda->ob, "add_discarded_message");
1548 driver_hook[H_MSG_DISCARDED].u.lambda->ob = ref_object(ip->ob, "add_discarded_message");
1549 }
1550
1551 push_ref_valid_object(inter_sp, ip->ob, "add_discarded_message");
1552
1553 call_lambda(&driver_hook[H_MSG_DISCARDED], 1);
1554
1555 if (inter_sp->type == T_STRING)
1556 {
1557 /* The new discarded_msg. Adopt the reference. */
1558 discarded_msg = inter_sp->u.str;
1559
1560 inter_sp->type = T_INVALID;
1561 inter_sp--;
1562 }
1563 else
1564 {
1565 pop_stack();
1566 discarded_msg = NULL;
1567 }
1568 }
1569 else if (driver_hook[H_MSG_DISCARDED].type == T_STRING)
1570 {
1571 discarded_msg = ref_mstring(driver_hook[H_MSG_DISCARDED].u.str);
1572 }
1573 else
1574 {
1575 discarded_msg = ref_mstring(STR_DISCARDED_MSG);
1576 }
1577
1578 if (discarded_msg)
1579 {
1580 /* Append it to the write buffer. */
1581 comm_socket_write(get_txt(discarded_msg), mstrsize(discarded_msg)
1582 , ip, WB_NONDISCARDABLE);
1583 free_mstring(discarded_msg);
1584 }
1585
1586 ip->msg_discarded = DM_INFO_WAS_SENT;
1587
1588 if (!ip->message_length)
1589 remove_flush_entry(ip);
1590 }
1591
1592 /*-------------------------------------------------------------------------*/
1593 void
1594 add_message (const char *fmt, ...)
1595
1596 /* Send a message to the current command_giver. The message is composed
1597 * from the <fmt> string and the following arguments using the normal
1598 * printf() semantics.
1599 *
1600 * The format string "%s" is special in that it bypasses the normal
1601 * printf() handling and uses the given char* argument directly as data
1602 * source, allowing to send strings of arbitrary length.
1603 * The format string FMT_STRING accepts a string_t argument of arbitrary length.
1604 * The format string FMT_BINARY accepts a char* as text argument, followed
1605 * by a size_t with the string length. The text may contain any character.
1606 *
1607 * All other format strings compose the message to send in a local buffer
1608 * and are therefore subject to a length restriction.
1609 *
1610 * This function also does the telnet, snooping, and shadow handling.
1611 * If an interactive player is shadowed, object.c::shadow_catch_message()
1612 * is called to give the shadows the opportunity to intercept the message.
1613 *
1614 * All messages are accumulated in interactive.message_buf, which is
1615 * flushed when it is full. This flush can be forced by passing the
1616 * special 'string' message_flush (which is actually just a NULL pointer)
1617 * as <fmt> string to this function.
1618 *
1619 * Messages which can't be send (e.g. because the command_giver was
1620 * destructed or disconnected) are printed on stdout, preceeded by ']'.
1621 *
1622 * If an error other than EINTR occured while sending the data to
1623 * the network, the message is discarded and the socket is marked
1624 * for disconnection.
1625 *
1626 * Note that add_message() might be called recursively.
1627 */
1628
1629 {
1630 char buff[MAX_TEXT + MAX_TEXT/2];
1631 /* Composition buffer for the final message.
1632 * We hope that it's big enough, but to be sure the code will
1633 * check for buffer overruns.
1634 * Message is composed starting from buff[1] on, buff[0] is
1635 * set to '%' for easier snooper-message generation.
1636 */
1637 int length;
1638 int min_length;
1639 /* When accumulating data in ip.message_buf[], this is the
1640 * threshold over which the buffer will be written to the
1641 * socket.
1642 * TODO: Actually, it is used just as a flag for flush/non-flush.
1643 */
1644 string_t *srcstr;
1645 /* If not NULL, this string was passed in to be printed.
1646 * source will point to the first real character of it.
1647 */
1648 int old_message_length; /* accumulated message length so far */
1649 char *source; /* Pointer to the final message to add */
1650 size_t srclen; /* Length of the message in source/srcstr */
1651 char *end; /* One char past the end of .message_buf[] */
1652 char *dest; /* First free char in .message_buf[] */
1653 va_list va;
1654 interactive_t *ip; /* The interactive user */
1655 object_t *snooper; /* Snooper of <ip> */
1656
1657 source = NULL;
1658 srcstr = NULL;
1659 srclen = 0;
1660 length = 0;
1661
1662 va_start(va, fmt);
1663
1664 /* Test if the command_giver is a real, living, undestructed user,
1665 * and not disconnected, closing or actually a new ERQ demon.
1666 * If the command_giver fails the test, the message is printed
1667 * to stdout and the function returns.
1668 */
1669 if ( command_giver == NULL
1670 || ( command_giver->flags & O_DESTRUCTED
1671 && fmt != message_flush )
1672 || !(O_SET_INTERACTIVE(ip, command_giver))
1673 || (ip->do_close && fmt != message_flush && !sending_telnet_command)
1674 )
1675 {
1676 putchar(']');
1677 if ( fmt == FMT_STRING )
1678 {
1679 /* Make sure to print embedded '\0' characters as well */
1680
1681 size_t len;
1682
1683 srcstr = va_arg(va, string_t *);
1684 source = get_txt(srcstr);
1685 srclen = mstrsize(srcstr);
1686
1687 for ( len = 0; len < srclen; )
1688 {
1689 if (*source == '\0')
1690 {
1691 putc('\0', stdout);
1692 source++;
1693 len++;
1694 }
1695 else
1696 {
1697 size_t slen;
1698
1699 fputs(source, stdout);
1700 slen = strlen(source);
1701 source += slen;
1702 len += slen;
1703 }
1704 }
1705 }
1706 else if ( fmt != message_flush )
1707 {
1708 vprintf(fmt, va);
1709 }
1710 fflush(stdout);
1711 va_end(va);
1712 return;
1713 }
1714
1715 old_message_length = ip->message_length;
1716
1717 /* --- Compose the final message --- */
1718
1719 /* Create the final message and handle snoopers and shadows.
1720 */
1721
1722 min_length = MAX_SOCKET_PACKET_SIZE-1;
1723 /* Allow some wiggle room for source characters like NL which
1724 * expand into two characters.
1725 */
1726
1727 if ( fmt == message_flush )
1728 {
1729 /* Just flush, nothing to add */
1730
1731 min_length = 1;
1732 source = "";
1733 srclen = 0;
1734 srcstr = NULL;
1735 }
1736 else /* add the message */
1737 {
1738 #ifdef COMM_STAT
1739 add_message_calls++;
1740 #endif
1741
1742 /* Compose the final message in buff[] (while checking for overruns)
1743 * and point source to it.
1744 * Recognize the special formats '%s', FMT_STRING and FMT_BINARY
1745 * to bypass buff[] for messages of arbitrary length and content.
1746 */
1747
1748 if (fmt == FMT_STRING)
1749 {
1750 srcstr = va_arg(va, string_t *);
1751 va_end(va);
1752
1753 source = get_txt(srcstr);
1754 srclen = mstrsize(srcstr);
1755 }
1756 else if (fmt == FMT_BINARY)
1757 {
1758 source = va_arg(va, char *);
1759 srclen = va_arg(va, size_t);
1760 va_end(va);
1761 srcstr = NULL;
1762 }
1763 else if (fmt[0] == '%' && fmt[1] == 's' && !fmt[2])
1764 {
1765 source = va_arg(va, char *);
1766 va_end(va);
1767 srclen = strlen(source);
1768 srcstr = NULL;
1769 }
1770 else
1771 {
1772 size_t len;
1773 len = vsnprintf(buff+1, sizeof(buff)-1, fmt,va);
1774 va_end(va);
1775 /* old sprintf() implementations returned -1 if the output was
1776 * truncated. Since size_t is an unsigned type, the check for
1777 * len == -1 is implicitly included by >= sizeof(...)-1, because
1778 * -1 will be wrapped to SIZE_T_MAX which is the maximum sizeof()
1779 * can return and can never be valid as return value here. */
1780 if (len >= sizeof(buff)-1)
1781 {
1782 char err[] = "\n*** Message truncated ***\n";
1783 debug_message("%s Message too long (Length: %zu): '%.200s...'\n"
1784 , time_stamp(), len, buff);
1785 (void)strcpy(buff+(sizeof(buff)-sizeof(err)), err);
1786 }
1787 source = buff+1;
1788 srclen = strlen(buff+1);
1789 srcstr = NULL;
1790 }
1791
1792 /* If we're not sending a telnet command with this message,
1793 * pass on the new data to any snooper and/or shadow
1794 */
1795
1796 if (!sending_telnet_command)
1797 {
1798
1799 /* If there's a shadow successfully handling the
1800 * message, return.
1801 * This may cause a recursive call to add_message()!.
1802 */
1803
1804 if (shadow_catch_message(command_giver, source))
1805 {
1806 return;
1807 }
1808
1809 /* If there's a snooper, send it the new message prepended
1810 * with a '%'.
1811 * For interactive snoopers this means a recursion with
1812 * the command_giver set to the snooper, for non-interactive
1813 * snoopers it's a simple call to tell_npc(), with an
1814 * adaption of the global trace_level to this users trace
1815 * settings.
1816 */
1817
1818 if ( NULL != (snooper = ip->snoop_by)
1819 && !(snooper->flags & O_DESTRUCTED))
1820 {
1821 buff[0] = '%';
1822 if (O_IS_INTERACTIVE(snooper))
1823 {
1824 object_t *save;
1825
1826 save = command_giver;
1827 command_giver = snooper;
1828 if (source != buff+1)
1829 {
1830 if (srcstr != NULL)
1831 {
1832 add_message("%s", "%");
1833 add_message(FMT_STRING, srcstr);
1834 }
1835 else if (srclen >= sizeof buff - 1)
1836 {
1837 add_message("%s", "%");
1838 add_message("%s", source);
1839 }
1840 else
1841 {
1842 strcpy(buff+1, source);
1843 add_message("%s", buff);
1844 }
1845 }
1846 else
1847 {
1848 add_message("%s", buff);
1849 }
1850 command_giver = save;
1851 }
1852 else
1853 {
1854 trace_level |= ip->trace_level;
1855 if (source != buff+1)
1856 {
1857 if (srcstr != NULL)
1858 {
1859 tell_npc(snooper, STR_PERCENT);
1860 tell_npc(snooper, srcstr);
1861 }
1862 else if (srclen >= sizeof buff - 1)
1863 {
1864 tell_npc(snooper, STR_PERCENT);
1865 tell_npc_str(snooper, source);
1866 }
1867 else
1868 {
1869 strcpy(buff+1, source);
1870 tell_npc_str(snooper, buff);
1871 }
1872 } else
1873 {
1874 tell_npc_str(snooper, buff);
1875 }
1876 }
1877 } /* if (snooper) */
1878 } /* if (!sending_telnet_command */
1879 } /* if (flush or not) */
1880
1881 #ifdef DEBUG
1882 if (d_flag > 1)
1883 debug_message("%s [%s (%zu)]: %s"
1884 , time_stamp(), get_txt(command_giver->name)
1885 , srclen, source);
1886 #endif
1887
1888 /* --- Send the final message --- */
1889
1890 /* Append the final message to the .message_buf[], taking
1891 * care of all the necessary charset and telnet translations.
1892 */
1893
1894 dest = &ip->message_buf[old_message_length];
1895 end = &ip->message_buf[sizeof ip->message_buf];
1896
1897 /* If there's any recursive call, let it begin
1898 * at the start.
1899 */
1900 ip->message_length = 0;
1901
1902 /* This loop advances source until it reaches the end.
1903 * Every character encountered is copied, translated or fed
1904 * into the telnet machine.
1905 */
1906
1907 #ifdef DEBUG_TELNET
1908 if (sending_telnet_command)
1909 {
1910 char *cp;
1911 long left;
1912 printf("%s TDEBUG: '%s' Sending telnet (%zu bytes): "
1913 , time_stamp(), get_txt(ip->ob->name), strlen(source));
1914 for (cp = source, left = srclen; left > 0; cp++, left--)
1915 printf(" %02x", (unsigned char)*cp);
1916 printf("\n");
1917 }
1918 #endif
1919
1920 do /* while (srclen != 0) */
1921 {
1922 ptrdiff_t chunk; /* Current size of data in .message_buf[] */
1923 char c; /* Currently processed character */
1924
1925 while (srclen != 0 && dest != end)
1926 {
1927 c = *source++;
1928 srclen--;
1929
1930 /* Process the character:
1931 * - copy it if the corresponding .charset bit is set,
1932 * or if it's part of a telnet command.
1933 * - translate a '\n' into '\r\n'
1934 * - double an IAC if quote_iac is active.
1935 * - stop this loop if the source is exhausted or
1936 * if the buffer is full.
1937 */
1938 if (sending_telnet_command)
1939 {
1940 *dest++ = c;
1941 }
1942 else if (!(ip->charset[(c&0xff)>>3] & 1<<(c&7)))
1943 NOOP;
1944 else if (c == '\n')
1945 {
1946 if (dest + 1 == end)
1947 {
1948 /* Not enough space in the buffer - revisit this char
1949 * on the next time around */
1950 source--;
1951 srclen++;
1952 break;
1953 }
1954
1955 /* Insert CR before NL */
1956 *dest++ = '\r';
1957 *dest++ = c;
1958 }
1959 else if ( (unsigned char)c == IAC && ip->quote_iac)
1960 {
1961 if (dest + 1 == end)
1962 {
1963 /* Not enough space in the buffer - revisit this char
1964 * on the next time around */
1965 source--;
1966 srclen++;
1967 break;
1968 }
1969
1970 *dest++ = c;
1971 *dest++ = c;
1972 }
1973 else
1974 {
1975 *dest++ = c;
1976 }
1977
1978 /* Other characters are silently dropped */
1979 } /* while() */
1980
1981 /* Check how much data there is in .message_buf[].
1982 * If it is enough, send it, else terminate the outer loop
1983 * (because *source must be exhausted for this to happen).
1984 */
1985 chunk = dest - ip->message_buf;
1986 if (chunk < min_length)
1987 {
1988 break;
1989 }
1990
1991 /* Write .message_buf[] to the network. */
1992
1993 if (!comm_socket_write(ip->message_buf, (size_t)chunk, ip, 0))
1994 {
1995 if (old_message_length)
1996 clear_message_buf(ip);
1997 return;
1998 }
1999
2000 /* Continue with the processing of source */
2001 dest = &ip->message_buf[0];
2002 } while (srclen != 0);
2003
2004 /* --- Final touches --- */
2005
2006 ip->message_length = length = dest - ip->message_buf;
2007
2008 /* Update the list of interactives with pending data */
2009
2010 if ( length && !old_message_length )
2011 {
2012 /* Buffer became 'dirty': add this interactive to the list.
2013 */
2014 add_flush_entry(ip);
2015 }
2016 if ( !length && old_message_length ) /* buffer has become empty */
2017 {
2018 clear_message_buf(ip);
2019 }
2020 } /* add_message() */
2021
2022 /*-------------------------------------------------------------------------*/
2023 static INLINE void
2024 reset_input_buffer (interactive_t *ip)
2025
2026 /* When returning from CHARMODE to LINEMODE, the input buffer variables
2027 * need to be reset. This function takes care of it.
2028 * Note that there might be additional lines pending between .tn_end and
2029 * .text_end.
2030 */
2031
2032 {
2033 if (ip->command_start)
2034 {
2035 DTN(("reset input buffer: cmd_start %hd, tn_start %hd, tn_end %hd, text_end %hd\n",
2036 ip->command_start, ip->tn_start, ip->tn_end, ip->text_end));
2037 ip->tn_start -= ip->command_start;
2038 ip->tn_end -= ip->command_start;
2039 ip->text_end -= ip->command_start;
2040 if (ip->tn_start < 0)
2041 ip->tn_start = 0;
2042 if (ip->tn_end < 0)
2043 ip->tn_end = 0;
2044 if (ip->text_end <= 0)
2045 ip->text_end = 0;
2046 else
2047 {
2048 move_memory( ip->text, ip->text + ip->command_start
2049 , ip->text_end
2050 );
2051 }
2052 if (ip->command_end)
2053 ip->command_end = ip->tn_end;
2054 ip->command_start = 0;
2055 }
2056 } /* reset_input_buffer() */
2057
2058 /*-------------------------------------------------------------------------*/
2059 static void
2060 add_flush_entry (interactive_t *ip)
2061
2062 /* Add the given interactive <ip> to the list of 'dirty' interactives.
2063 * The function is safe to call for interactives already in the list.
2064 */
2065
2066 {
2067 if ( ip->previous_player_for_flush || first_player_for_flush == ip)
2068 return;
2069
2070 if ( NULL != (ip->next_player_for_flush = first_player_for_flush) )
2071 {
2072 first_player_for_flush->previous_player_for_flush = ip;
2073 }
2074 ip->previous_player_for_flush = NULL;
2075 first_player_for_flush = ip;
2076 } /* add_flush_entry() */
2077
2078 /*-------------------------------------------------------------------------*/
2079 static void
2080 remove_flush_entry (interactive_t *ip)
2081
2082 /* Remove the given interactive <ip> from the list of 'dirty' interactives
2083 * and make sure it is really clean. The function is safe to call for
2084 * interactives not in the list.
2085 */
2086
2087 {
2088 /* To make it safe for calling the function even for interactives
2089 * not in the flush list, we check that <ip> is either in the middle
2090 * or at the end of the flush list (one or both of the .previous
2091 * and .next pointers is !NULL), or if .previous is NULL, that it is
2092 * the first entry in the list.
2093 */
2094
2095 if ( ip->previous_player_for_flush )
2096 {
2097 ip->previous_player_for_flush->next_player_for_flush
2098 = ip->next_player_for_flush;
2099 }
2100 else if (first_player_for_flush == ip)
2101 {
2102 first_player_for_flush = ip->next_player_for_flush;
2103 }
2104
2105 if ( ip->next_player_for_flush )
2106 {
2107 ip->next_player_for_flush->previous_player_for_flush
2108 = ip->previous_player_for_flush;
2109 }
2110
2111 ip->previous_player_for_flush = NULL;
2112 ip->next_player_for_flush = NULL;
2113 } /* remove_flush_entry() */
2114
2115 /*-------------------------------------------------------------------------*/
2116 void
2117 flush_all_player_mess (void)
2118
2119 /* Flush all pending data from the interactives. Usually called before
2120 * every input loop, after a user logged in, or after an LPC runtime
2121 * error was processed.
2122 */
2123
2124 {
2125 interactive_t *ip, *nip;
2126 object_t *save = command_giver;
2127
2128 for ( ip = first_player_for_flush; ip != NULL; ip = nip)
2129 {
2130 nip = ip->next_player_for_flush;
2131 /* add_message() will clobber (ip)->next_player_for_flush! */
2132 command_giver = ip->ob;
2133 add_message(message_flush);
2134
2135 if(ip->msg_discarded == DM_SEND_INFO)
2136 add_discarded_message(ip);
2137 }
2138 command_giver = save;
2139 } /* flush_all_player_mess() */
2140
2141 /*-------------------------------------------------------------------------*/
2142 static void
2143 clear_message_buf (interactive_t *ip)
2144
2145 /* Clear the buffer of the given interactive <ip> and remove it from
2146 * the list of 'dirty' interactives if there is nothing else to do.
2147 * The function is safe to call for interactives not in the list.
2148 *
2149 * This function is called after an interactive sent all pending data (or
2150 * failing while doing so).
2151 */
2152
2153 {
2154 ip->message_length = 0;
2155
2156 if (ip->msg_discarded != DM_SEND_INFO)
2157 remove_flush_entry(ip);
2158 } /* clear_message_buf() */
2159
2160 /*-------------------------------------------------------------------------*/
2161 Bool
2162 get_message (char *buff)
2163
2164 /* Get a message from a user, or wait until it is time for the next
2165 * heartbeat/callout. You can tell this apart by the result:
2166 *
2167 * true: a user message was received and placed into buff; the user
2168 * object is set as command_giver.
2169 * false: it is just time to call the heart_beat.
2170 *
2171 * In both cases, time_to_call_heart_beat is set if a heartbeat is due.
2172 *
2173 * Internally, get_message() scans the array of interactive users in
2174 * search for one with a complete message in its incoming buffer. If
2175 * an earlier select() marked the socket for the current user as pending
2176 * with data, this data is read into the buffer before the check for
2177 * a message is performed. get_message() returns for the first user found
2178 * with a complete message. Since get_message() keeps its own
2179 * status of which user was looked at last, the next call to get_message()
2180 * will continue the scan where it left off.
2181 *
2182 * If no user has a complete message, a call to select() waits for more
2183 * incoming data. If this succeeds (and no heartbeat requires an
2184 * immediate return), the cycle begins again. If a heart_beat is due
2185 * even before select() executed, the waiting time for select() is
2186 * set to 0 so that only the status of the sockets is recorded and
2187 * get_message returns (almost) immediately.
2188 *
2189 * Normally, users can give only one command per cycle. The exception
2190 * is when they are editing, then they can give up to ALLOWED_ED_CMDS.
2191 *
2192 * Heartbeats are detected by checking the backend variable comm_time_-
2193 * to_call_heart_beat, which is set by the SIGALRM handler. If it is
2194 * true, get_message() sets the variable time_to_call_heart_beat to
2195 * inform the backend and returns.
2196 *
2197 * If a heart_beat occurs during the reading and returning of player
2198 * commands, the comm_time_c_h_b variable is set, but not evaluated.
2199 * This evaluation happens only when a select() is performed (therefore
2200 * the second variable time_to_c_h_b). This way every user can issure
2201 * at least one command in one backend cycle, even if that takes longer
2202 * than one heart_beat time. This makes it also legal for comm_to_c_h_b
2203 * to be set upon entering get_message().
2204 *
2205 * For short latency, the UDP socket is checked on every call to
2206 * get_message(), even if a previous select() did not mark it as ready
2207 * (this is disabled under BeOS and Windows).
2208 */
2209
2210 {
2211 /* State information: */
2212 static fd_set readfds, writefds;
2213 /* List of sockets with pending data.
2214 * You can ignore a 'could be used uninitialized' warning.
2215 */
2216 static int NextCmdGiver = -1;
2217 /* Index of current user to check */
2218 static int CmdsGiven = 0;
2219 /* Number of commands the current user gave in this cycle. */
2220
2221 # define StartCmdGiver (max_player)
2222 # define DecreaseCmdGiver NextCmdGiver--
2223
2224 int i;
2225 interactive_t * ip = NULL;
2226 fd_set exceptfds;
2227
2228
2229 /* The endless loop */
2230
2231 while(MY_TRUE)
2232 {
2233 struct sockaddr_in addr;
2234 length_t length; /* length of <addr> */
2235 struct timeval timeout;
2236
2237 /* --- select() on the sockets and handle ERQ --- */
2238
2239 /* This also removes users which connection is marked
2240 * as to be closed.
2241 */
2242
2243 if (NextCmdGiver < 0)
2244 {
2245 int nfds; /* number of fds for select() */
2246 int res; /* result from select() */
2247 int twait; /* wait time in seconds for select() */
2248 int retries; /* retries of select() after EINTR */
2249
2250 flush_all_player_mess();
2251 twait = comm_time_to_call_heart_beat ? 0 : 1;
2252 /* If the heart_beat is due, just check the state
2253 * of the sockets, but don't wait.
2254 */
2255
2256 /* Set up fd-sets. */
2257
2258 FD_ZERO(&readfds);
2259 FD_ZERO(&writefds);
2260 for (i = 0; i < numports; i++) {
2261 FD_SET(sos[i], &readfds);
2262 } /* for */
2263 nfds = min_nfds;
2264 for (i = max_player + 1; --i >= 0;)
2265 {
2266 ip = all_players[i];
2267 if (!ip)
2268 continue;
2269
2270 if (ip->do_close)
2271 {
2272 ip->do_close &= FLAG_PROTO_ERQ;
2273 remove_interactive(ip->ob, MY_FALSE);
2274 continue;
2275 }
2276
2277 if (ip->tn_state == TS_READY)
2278 {
2279 /* If telnet is ready for commands, react quickly. */
2280 twait = 0;
2281 }
2282 else
2283 {
2284 FD_SET(ip->socket, &readfds);
2285 if (socket_number(ip->socket) >= nfds)
2286 nfds = socket_number(ip->socket)+1;
2287 }
2288
2289 if (ip->write_first != NULL)
2290 {
2291 /* There is something to write. */
2292 FD_SET(ip->socket, &writefds);
2293 }
2294
2295 } /* for (all players) */
2296 #ifdef ERQ_DEMON
2297 if (erq_demon >= 0)
2298 {
2299 FD_SET(erq_demon, &readfds);
2300 }
2301 #endif
2302 if (udp_s >= 0)
2303 {
2304 FD_SET(udp_s, &readfds);
2305 }
2306
2307 #ifdef USE_PGSQL
2308 pg_setfds(&readfds, &writefds, &nfds);
2309 #endif
2310
2311 /* select() until time is up or there is data */
2312
2313 for (retries = 6;;)
2314 {
2315 check_alarm();
2316 timeout.tv_sec = twait;
2317 timeout.tv_usec = 0;
2318 res = socket_select(nfds, &readfds, &writefds, 0, &timeout);
2319 if (res == -1)
2320 {
2321 if (errno == EINTR)
2322 {
2323 /* We got an alarm, probably need heart_beat.
2324 * But finish the select call since we already have
2325 * prepared readfds.
2326 */
2327 if (comm_time_to_call_heart_beat)
2328 twait = 0;
2329 if (--retries >= 0)
2330 continue;
2331 }
2332 else
2333 {
2334 perror("select");
2335 }
2336
2337 /* Despite the failure, pretend select() suceeded with
2338 * zero sockets to read, and process heart_beat / buffered
2339 * commands.
2340 */
2341 FD_ZERO(&readfds);
2342 }
2343 break;
2344 } /* for (retries) */
2345
2346 /* If we got a SIGIO/SIGURG, telnet wants to synch with us.
2347 */
2348 if (urgent_data)
2349 {
2350 DTN(("telnet wants to sync\n"));
2351 check_alarm();
2352 urgent_data = MY_FALSE;
2353 timeout.tv_sec = 0;
2354 timeout.tv_usec = 0;
2355 memset((char *)&exceptfds, 255, (size_t)(nfds + 7) >> 3);
2356 if (socket_select(nfds, 0, 0, &exceptfds, &timeout) > 0)
2357 {
2358 for (i = max_player + 1; --i >= 0;)
2359 {
2360 ip = all_players[i];
2361 if (!ip)
2362 continue;
2363 if (FD_ISSET(ip->socket, &exceptfds))
2364 {
2365 DTN(("ts_data = TS_SYNCH\n"));
2366 ip->ts_data = TS_SYNCH;
2367 switch (ip->tn_state)
2368 {
2369 case TS_DATA:
2370 case TS_READY:
2371 ip->tn_state = TS_SYNCH;
2372 ip->gobble_char = '\0';
2373 DTN(("tn_state = TS_SYNCH\n"));
2374 }
2375 }
2376 } /* for (all players) */
2377 }
2378 /* Maybe the data didn't arrive yet, so try again later.
2379 * But don't waste time doing it for too long.
2380 */
2381 else if (current_time - urgent_data_time < 600)
2382 {
2383 urgent_data = MY_TRUE;
2384 }
2385 } /* if (urgent_data) */
2386
2387 #ifdef USE_PGSQL
2388 pg_process_all();
2389 #endif
2390
2391 /* Initialise the user scan */
2392 CmdsGiven = 0;
2393 NextCmdGiver = StartCmdGiver;
2394
2395 #ifdef ERQ_DEMON
2396
2397 /* --- Handle data from the ERQ ---
2398 * TODO: This should be a function on its own.
2399 * TODO: Define the erq messages as structs.
2400 */
2401 if (erq_demon >= 0 && FD_ISSET(erq_demon, &readfds))
2402 {
2403 mp_int l;
2404 mp_int msglen; /* Length of the current erq message */
2405 mp_int rest;
2406 int32 handle;
2407 char *rp; /* Read pointer into buf_from_erq[] */
2408
2409 FD_CLR(erq_demon, &readfds);
2410
2411 /* Try six times to read data from the ERQ, appending
2412 * it to what is already in buf_from_erq[].
2413 */
2414 retries = 6;
2415 do {
2416 l = socket_read(
2417 erq_demon,
2418 input_from_erq,
2419 (size_t)(&buf_from_erq[sizeof buf_from_erq] - input_from_erq)
2420 );
2421 } while(l < 0 && errno == EINTR && --retries >= 0);
2422
2423 /* If there is no data, stop the erq, else handle it. */
2424
2425 if (l <= 0)
2426 {
2427 #ifdef DEBUG_ERQ
2428 fprintf(stderr, "%s read %"PRIdMPINT" bytes from erq demon\n"
2429 , time_stamp(), l);
2430 if (l)
2431 perror("");
2432 #endif /* DEBUG_ERQ */
2433 stop_erq_demon(MY_TRUE);
2434 }
2435 else
2436 {
2437 input_from_erq += l;
2438 l = input_from_erq - &buf_from_erq[0];
2439 rp = buf_from_erq;
2440
2441 /* l is the amount of data left to consider,
2442 * rp points to the data to be considered next.
2443 *
2444 * Loop while there are messages left in the buffer.
2445 */
2446
2447 for (; l >= 8 && l >= (msglen = read_32(rp))
2448 ; rp += msglen, l -= msglen)
2449 {
2450 Bool keep_handle;
2451
2452 /* Is the message length valid?
2453 * TODO: use sizeof(struct) here
2454 */
2455 if (msglen < 8) {
2456 #ifdef DEBUG_ERQ
2457 fprintf( stderr
2458 , "%s invalid length of message from"
2459 "erq demon: %"PRIdMPINT" bytes\n"
2460 , time_stamp(), msglen);
2461 #endif /* DEBUG_ERQ */
2462 stop_erq_demon(MY_TRUE);
2463 break;
2464 }
2465
2466 handle = read_32(rp+4); /* get the handle */
2467
2468 if (handle == ERQ_HANDLE_KEEP_HANDLE
2469 && msglen >= 8)
2470 {
2471 /* _KEEP_HANDLE wrapper are used when
2472 * more messages for the (real) handle
2473 * are to be expected. The real message
2474 * follows after the _KEEP_HANDLE.
2475 */
2476 handle = read_32(rp+8); /* the real handle */
2477 keep_handle = MY_TRUE;
2478 msglen -= 4; /* adjust the message parameters */
2479 l -= 4;
2480 rp += 4;
2481 }
2482 else if (handle == ERQ_HANDLE_RLOOKUP)
2483 {
2484 /* The result of a hostname lookup. */
2485
2486 if (msglen < 13 || rp[msglen-1]) {
2487 #ifdef DEBUG
2488 if (msglen == 12) {
2489 if (d_flag > 1)
2490 debug_message("%s Host lookup failed\n"
2491 , time_stamp());
2492 } else {
2493 debug_message("%s Bogus reverse name lookup.\n"
2494 , time_stamp());
2495 }
2496 #endif
2497 } else {
2498 uint32 naddr;
2499 struct in_addr net_addr;
2500
2501 memcpy((char*)&naddr, rp+8, sizeof(naddr));
2502 #ifndef USE_IPV6
2503 net_addr.s_addr = naddr;
2504 #else
2505 CREATE_IPV6_MAPPED(&net_addr, naddr);
2506 #endif
2507 add_ip_entry(net_addr, rp+12);
2508 }
2509 continue;
2510 }
2511 #ifdef USE_IPV6
2512 else if (handle == ERQ_HANDLE_RLOOKUPV6)
2513 {
2514 /* The result of a hostname lookup. */
2515
2516 if (msglen < 9 || rp[msglen-1]) {
2517 #ifdef DEBUG
2518 debug_message("%s Bogus reverse name lookup.\n"
2519 , time_stamp());
2520 #else
2521 NOOP;
2522 #endif
2523 } else {
2524 char * space;
2525
2526 space = strchr(rp+8, ' ');
2527
2528 if (space == NULL)
2529 {
2530 debug_message("%s IP6 Host lookup failed: %s\n"
2531 , time_stamp(), rp+8);
2532 }
2533 else if (strlen(space+1))
2534 {
2535 *space = '\0';
2536 update_ip_entry(rp+8, space+1);
2537 }
2538 }
2539 continue;
2540 }
2541 #endif /* USE_IPV6 */
2542 else
2543 {
2544 /* remove the callback handle after processing
2545 * the message.
2546 */
2547 keep_handle = MY_FALSE;
2548 }
2549
2550 /* We have an ERQ message for a user supplied
2551 * handle - execute it (after some sanity checks).
2552 */
2553
2554 rest = msglen - 8;
2555 if ((uint32)handle < MAX_PENDING_ERQ
2556 && pending_erq[handle].fun.type != T_INVALID
2557 && ( rest <= (mp_int)max_array_size
2558 || !max_array_size
2559 || pending_erq[handle].string_arg
2560 )
2561 )
2562 {
2563 svalue_t *erqp = &pending_erq[handle].fun;
2564 object_t *ob;
2565 wiz_list_t *user;
2566 int num_arg;
2567
2568 command_giver = 0;
2569 current_interactive = 0;
2570 ob = !CLOSURE_MALLOCED(erqp->x.closure_type)
2571 ? erqp->u.ob
2572 : erqp->u.lambda->ob;
2573 if (pending_erq[handle].string_arg)
2574 {
2575 string_t * str;
2576
2577 str = new_n_mstring(rp + 8, rest);
2578 push_string(inter_sp, str);
2579
2580 num_arg = 1;
2581 }
2582 else
2583 {
2584 unsigned char *cp;
2585 vector_t *v;
2586 svalue_t *svp;
2587
2588 current_object = ob;
2589 v = allocate_array(rest);
2590 current_object = NULL;
2591 push_array(inter_sp, v);
2592 push_number(inter_sp, rest);
2593 cp = (unsigned char *)rp + 8;
2594 for (svp = v->item; --rest >=0; svp++)
2595 {
2596 svp->u.number = *cp++;
2597 }
2598
2599 num_arg = 2;
2600 }
2601
2602 user = ob->user;
2603 if (user->last_call_out != current_time)
2604 {
2605 user->last_call_out = current_time;
2606 CLEAR_EVAL_COST;
2607 } else {
2608 assigned_eval_cost = eval_cost = user->call_out_cost;
2609 }
2610 RESET_LIMITS;
2611 secure_callback_lambda(erqp, num_arg);
2612 user->call_out_cost = eval_cost;
2613 if (!keep_handle || (ob->flags & O_DESTRUCTED))
2614 {
2615 free_svalue(erqp);
2616 erqp->type = T_INVALID;
2617 erqp->u.generic = (void *)free_erq;
2618 free_erq = &pending_erq[handle];
2619 }
2620 } /* if(valid handle) */
2621
2622 /* Messages for invalid handles are no error: e.g. the
2623 * object could have gone away unexpectantly before
2624 * the erq had time to answer.
2625 */
2626
2627 } /* for (l,rp in buf_from_erq) */
2628
2629 /* Delete the processed data from the buffer */
2630 if (rp != buf_from_erq)
2631 {
2632 move_memory(buf_from_erq, rp, (size_t)l);
2633 input_from_erq = &buf_from_erq[l];
2634 }
2635 } /* if (read data from erq) */
2636 } /* if (erq socket ready) */
2637
2638 #endif /* ERQ_DEMON */
2639
2640 /* --- Try to get a new player --- */
2641 for (i = 0; i < numports; i++)
2642 {
2643 if (FD_ISSET(sos[i], &readfds))
2644 {
2645 SOCKET_T new_socket;
2646
2647 length = sizeof addr;
2648 new_socket = accept(sos[i], (struct sockaddr *)&addr
2649 , &length);
2650 if ((int)new_socket != -1)
2651 new_player( NULL, new_socket, &addr, (size_t)length
2652 , port_numbers[i]);
2653 else if ((int)new_socket == -1
2654 && errno != EWOULDBLOCK && errno != EINTR
2655 && errno != EAGAIN && errno != EPROTO )
2656 {
2657 /* EBADF would be a valid cause for an abort,
2658 * same goes for ENOTSOCK, EOPNOTSUPP, EFAULT.
2659 * However, don't abort() because that tends to
2660 * leave Mud admins baffled (and would opens the
2661 * door for DoS attacks).
2662 */
2663 int errorno = errno;
2664 fprintf( stderr
2665 , "%s comm: Can't accept on socket %d "
2666 "(port %d): %s\n"
2667 , time_stamp(), sos[i], port_numbers[i]
2668 , strerror(errorno)
2669 );
2670 debug_message("%s comm: Can't accept on socket %d "
2671 "(port %d): %s\n"
2672 , time_stamp(), sos[i], port_numbers[i]
2673 , strerror(errorno)
2674 );
2675 /* TODO: Was: perror(); abort(); */
2676 }
2677 }
2678 } /* for */
2679 /* check for alarm signal (heart beat) */
2680 if (comm_time_to_call_heart_beat)
2681 {
2682 time_to_call_heart_beat = MY_TRUE;
2683 return MY_FALSE;
2684 }
2685 } /* if (no NextCmdGiver) */
2686
2687 /* See if we got any udp messages.
2688 * We don't test readfds so that we can accept udp messages with
2689 * short latency. But for the same reason, it was necessary to
2690 * include the descriptor number in the set to be selected on.
2691 * Note for Cygwin: since making sockets non-blocking
2692 * is a bit tricky, we check if the socket is actually ready,
2693 * to prevent freezing.
2694 * TODO: Always use the readfds information.
2695 */
2696 #if !defined(CYGWIN)
2697 if (udp_s >= 0)
2698 #else
2699 if (udp_s >= 0 && FD_ISSET(udp_s, &readfds))
2700 #endif
2701 {
2702 char *ipaddr_str;
2703 int cnt;
2704
2705 length = sizeof addr;
2706 cnt = recvfrom(udp_s, udp_buf, sizeof(udp_buf)-1, 0
2707 , (struct sockaddr *)&addr, &length);
2708 if (cnt != -1)
2709 {
2710 string_t *udp_data;
2711
2712 udp_data = new_n_mstring(udp_buf, cnt);
2713 if (!udp_data)
2714 {
2715 debug_message("%s Out of memory (%d bytes) for UDP message.\n"
2716 , time_stamp(), cnt);
2717 }
2718 else
2719 {
2720 command_giver = NULL;
2721 current_interactive = NULL;
2722 current_object = NULL;
2723 trace_level = 0;
2724 #ifndef USE_IPV6
2725 ipaddr_str = inet_ntoa(addr.sin_addr);
2726 #else
2727 ipaddr_str = inet6_ntoa(addr.sin_addr);
2728 #endif
2729 push_c_string(inter_sp, ipaddr_str);
2730 push_string(inter_sp, udp_data); /* adopts the ref */
2731 push_number(inter_sp, ntohs(addr.sin_port));
2732 RESET_LIMITS;
2733 callback_master(STR_RECEIVE_UDP, 3);
2734 CLEAR_EVAL_COST;
2735 }
2736 }
2737 } /* if (upd_s) */
2738
2739 /* --- The Scan for User Commands --- */
2740
2741 for (; NextCmdGiver >= 0; DecreaseCmdGiver)
2742 {
2743 object_t *snooper;
2744
2745 ip = all_players[NextCmdGiver];
2746
2747 if (ip == 0)
2748 continue;
2749
2750 #ifdef USE_TLS
2751 /* Special case for setting up a TLS connection: don't
2752 * attempt IO if the connection is still being set up.
2753 */
2754 if (ip->tls_status == TLS_HANDSHAKING)
2755 {
2756 tls_continue_handshake(ip);
2757 continue;
2758 }
2759 #endif
2760
2761 if (FD_ISSET(ip->socket, &writefds))
2762 {
2763 comm_write_pending(ip);
2764 }
2765 /* Skip players which have reached the ip->maxNumCmds limit
2766 * for this second. We let the data accumulate on the socket.
2767 */
2768 if (ip->last_time == current_time
2769 && ip->maxNumCmds >= 0
2770 && ip->numCmds >= ip->maxNumCmds)
2771 continue;
2772
2773 /* Get the data (if any), at max enough to fill .text[] */
2774
2775 if (FD_ISSET(ip->socket, &readfds)) {
2776 int l;
2777
2778 l = MAX_TEXT - ip->text_end;
2779
2780 /* In CHARMODE with combine-charset, the driver gets
2781 * confused when receiving MAX_TEXT or more combinable
2782 * characters.
2783 * I couldn't quite figure out what and why, but
2784 * reading less than MAX_TEXT characters works around
2785 * the issue.
2786 */
2787 #ifndef SIMULATE_CHARMODE
2788 if ((ip->noecho & (CHARMODE_REQ|CHARMODE)) == (CHARMODE_REQ|CHARMODE))
2789 #else
2790 if (ip->noecho & (CHARMODE_REQ|CHARMODE))
2791 #endif
2792 {
2793 l -= 2;
2794 }
2795
2796 DTN(("text_end %hd, can read %d chars\n", ip->text_end, l));
2797
2798 #ifdef USE_TLS
2799 if (ip->tls_status != TLS_INACTIVE)
2800 l = tls_read(ip, ip->text + ip->text_end, (size_t)l);
2801 else
2802 #endif
2803 l = socket_read(ip->socket, ip->text + ip->text_end, (size_t)l);
2804 DTN(("# chars read: %d\n", l));
2805 if (l == -1)
2806 {
2807 switch (errno)
2808 {
2809 case EAGAIN:
2810 // There was no data for available for immediate read.
2811 // This should not happen for plain TCP connections, but
2812 // may for TLS connections.
2813 #ifdef USE_TLS
2814 if (ip->tls_status == TLS_INACTIVE)
2815 #endif
2816 debug_message("%s Got unexpected EAGAIN upon socket read. Retrying later.\n");
2817 // Fall-through
2818 case EINTR:
2819 // read was interrupted by a signal. Ignore and retry later again.
2820 continue;
2821 default:
2822 // we regard other errors as non-recoverable.
2823 debug_message("%s Error (%d) upon reading socket %d (ip %p '%s'), closing connection: %s\n"
2824 , time_stamp(), errno, ip->socket, ip,
2825 (ip->ob ? get_txt(ip->ob->name) : "<no name>"),
2826 strerror(errno));
2827 remove_interactive(ip->ob, MY_FALSE);
2828 continue;
2829 }
2830 }
2831 if (l == 0) // TODO: is this really such a severe error?
2832 {
2833 if (ip->closing)
2834 comm_fatal(ip, "Tried to read from closing socket.\n");
2835 /* This will forcefully disconnect the user */
2836 else
2837 remove_interactive(ip->ob, MY_FALSE);
2838 continue;
2839 }
2840 #ifdef COMM_STAT
2841 inet_packets_in++;
2842 inet_volume_in += l;
2843 #endif
2844
2845 ip->text_end += l;
2846
2847 /* Here would be the place to send data through an
2848 * outportal instead of returning it.
2849 */
2850
2851 telnet_neg(ip);
2852 } /* if (cmdgiver socket ready) */
2853
2854 /* if ip->text[0] does not hold a valid character, the outcome
2855 * of the comparison to input_escape does not matter.
2856 */
2857
2858 /* ----- CHARMODE -----
2859 * command_start is 0 at the beginning. Received chars start at
2860 * text[0]. After the first character is processed, command_start
2861 * will be 1. Chars are in text[1] then. Only after a
2862 * full_newline is command_start reset to 0. This is important for
2863 * bang-escape, the first char in a 'line' is stored in text[0],
2864 * subsequent chars are in text[1].
2865 *
2866 * chars_ready is the number of chars in the text buffer. If the
2867 * user is slow this will be 1. If the user pastes data it could
2868 * be more. The chars are processed then one at a time (or if
2869 * combine-charset is used that many until a non-combinable char
2870 * is reached).
2871 *
2872 * The processed char(s) are copied to buff and handled in the
2873 * backend.
2874 *
2875 * If telnet_neg() returned state READY, we want to process the
2876 * string end marker (which represents the \r\n) also and have to
2877 * add 1 to strlen() for the chars_ready.
2878 *
2879 * The remark above 'if (destix > 0 && !buff[destix-1])' is not
2880 * quite true (anymore). Because we process the string terminating
2881 * \0 as a char, we will have a destix > 0 always - even if we got
2882 * a new line. Mind, that buff[destix-1] is always buff[0] in
2883 * that 'if', because newlines are never combinable and we always
2884 * start with a new buffer for it!
2885 *
2886 #ifndef SIMULATE_CHARMODE
2887 * TODO: I dont think that it is neccesary to disable charmode if
2888 * TODO:: the client refuses to use it. The disadvantage of the
2889 * TODO:: present behaviour is a confused lpc object (which could
2890 * TODO:: not know if it gets linemode-lines). The charmode code
2891 * TODO:: does work with clients in linemode.
2892 #endif
2893 */
2894
2895 #ifndef SIMULATE_CHARMODE
2896 if ((ip->noecho & (CHARMODE_REQ|CHARMODE)) == (CHARMODE_REQ|CHARMODE))
2897 #else
2898 if (ip->noecho & (CHARMODE_REQ|CHARMODE))
2899 #endif
2900 {
2901 DTN(("CHARMODE_REQ\n"));
2902 if (ip->text[0] != input_escape
2903 || find_no_bang(ip) & IGNORE_BANG )
2904 {
2905 /* Unescaped input.
2906 * Puts the next character(s) (addressed by
2907 * .command_start) into buff[0] and return the data.
2908 */
2909
2910 int destix; /* Save index */
2911 Bool end_of_line = MY_FALSE;
2912
2913 DTN((" Unescaped input\n"));
2914
2915 if (ip->tn_state != TS_READY)
2916 {
2917 /* .text[] contains an incomplete negotiation.
2918 * Set .chars_ready the amount of pure data available
2919 * and temporarily suspend the telnet machine.
2920 */
2921 length = (TN_START_VALID(ip->tn_state)
2922 ? ip->tn_start
2923 : ip->command_end
2924 ) - ip->command_start;
2925 DTN((" incomplete negotiation: length %ld\n"
2926 , (long)length));
2927 if (!length)
2928 continue;
2929 if (length < 0)
2930 {
2931 comm_fatal(ip, "comm: data length < 0: %ld\n", (long)length);
2932 continue;
2933 }
2934 DTN((" save machine state %hhd, set to %d (READY)\n"
2935 , ip->tn_state, TS_READY));
2936 ip->save_tn_state = ip->tn_state;
2937 ip->chars_ready = length;
2938 ip->tn_state = TS_READY;
2939 }
2940 else if (!ip->chars_ready)
2941 {
2942 /* Empty input: we received an end of line.
2943 * The telnet machine is already suspended, but
2944 * we have to set the state for it to return to.
2945 * At the moment it is TS_INVALID, so the next
2946 * character received would be thrown away.
2947 */
2948 DTN((" Empty input: save machine state %d (DATA)\n"
2949 , TS_DATA));
2950 length = strlen(ip->text + ip->command_start) + 1;
2951 ip->chars_ready = length;
2952 ip->save_tn_state = TS_DATA;
2953 end_of_line = MY_TRUE;
2954 /* tn_state is TS_READY */
2955 }
2956
2957 /* Copy as many characters from the text[] into
2958 * the buff[] as possible.
2959 */
2960 DTN((" %"PRId32" chars ready\n", ip->chars_ready));
2961 if (end_of_line)
2962 {
2963 DTN((" faking NL\n"));
2964 buff[0] = '\n';
2965 destix = 1;
2966 }
2967 else for (destix = 0; destix < ip->chars_ready; )
2968 {
2969 char ch;
2970
2971 ch = ip->text[ip->command_start++];
2972 buff[destix++] = ch;
2973 if (!(ip->combine_cset[(ch&0xff) / 8] & (1 << (ch % 8)))
2974 || !ch
2975 )
2976 {
2977 /* This character can't be combined (or it is the
2978 * end of the line).
2979 * If it is not the first character encountered,
2980 * undo the previous store; in either case break
2981 * the loop.
2982 */
2983 if (destix != 1)
2984 {
2985 destix--;
2986 ip->command_start--;
2987 }
2988 break;
2989 }
2990 }
2991
2992 /* destix is now the number of characters stored in
2993 * buff[], and is at least 1.
2994 */
2995
2996 if (!buff[destix-1])
2997 {
2998 /* End of line. Reinitialise the telnet machine
2999 */
3000 DTN((" end of line: reinit telnet machine\n"));
3001 destix--;
3002 ip->command_start = 0;
3003 ip->tn_state = TS_DATA;
3004 telnet_neg(ip);
3005 }
3006
3007 buff[destix] = '\0';
3008
3009 if (!end_of_line)
3010 ip->chars_ready -= destix;
3011 DTN((" %"PRId32" chars left ready\n", ip->chars_ready));
3012 if (!ip->chars_ready)
3013 {
3014 /* All the pure data was read, now restore the
3015 * old telnet machine state.
3016 * Leave the first char in to make input escape
3017 * possible
3018 */
3019 DTN((" restore old telnet machine state %hhd\n"
3020 , ip->save_tn_state));
3021 ip->tn_state = ip->save_tn_state;
3022 ip->save_tn_state = TS_INVALID;
3023 ip->tn_start -= ip->command_start - 1;
3024 ip->command_end -= ip->command_start - 1;
3025
3026 if (ip->command_start && ip->command_end > 0)
3027 {
3028 move_memory( ip->text, ip->text+ip->command_start
3029 , ip->command_end
3030 );
3031 }
3032
3033 ip->command_start = 1;
3034
3035 /* When receiving a pure data line in charmode, starting
3036 * with the second char, these two values may become
3037 * negative. We have to correct them then to point
3038 * to ip->command_start.
3039 */
3040 DTN((" tn_start %hd, command_end %hd\n", ip->tn_start, ip->command_end));
3041 if (ip->tn_start < 1)
3042 ip->tn_start = 1;
3043 if (ip->command_end < 1)
3044 ip->command_end = 1;
3045
3046 ip->text_end = ip->tn_end = ip->command_end;
3047 }
3048
3049 command_giver = ip->ob;
3050 trace_level = ip->trace_level;
3051 DecreaseCmdGiver;
3052 CmdsGiven = 0;
3053
3054 if (ip->last_time != current_time)
3055 {
3056 ip->last_time = current_time;
3057 ip->numCmds = 0;
3058 }
3059 else
3060 ip->numCmds++;
3061
3062 DTN(("--- return with char command %02x '%c' length %d ---\n", buff[0], buff[0], destix));
3063
3064 return MY_TRUE;
3065 }
3066 else if (ip->tn_state != TS_READY)
3067 {
3068 DT(("'%s' Escaped input\n", get_txt(ip->ob->name)));
3069 length = (TN_START_VALID(ip->tn_state)
3070 ? ip->tn_start
3071 : ip->command_end
3072 ) - ip->command_start;
3073 DTN((" data length %ld\n", (long)length));
3074 if (length < 0)
3075 {
3076 comm_fatal(ip, "comm: data length < 0: %ld\n", (long)length);
3077 continue;
3078 }
3079 if (length > ip->chars_ready)
3080 {
3081 comm_socket_write(ip->text + ip->chars_ready
3082 , (size_t)(length - ip->chars_ready)
3083 , ip, 0);
3084 ip->chars_ready = length;
3085 }
3086 }
3087 } /* if (CHARMODE_REQ) */
3088
3089 /* The telnet negotiation produces the commands starting at
3090 * the beginning of .text[] and terminated with a '\0'. Whenever
3091 * a command is complete, the tn_state is TS_READY.
3092 */
3093 DTN(("tn complete, telnet machine state: %hhd\n", ip->tn_state));
3094 if (ip->tn_state == TS_READY)
3095 {
3096 /* We have a command: copy it into buff, handle a
3097 * possible snooper and return.
3098 */
3099
3100 DTN(("telnet machine ready\n"));
3101 /* buffer overflows here are impossible even with strcpy(),
3102 * because buff is allocated in backend() as MAX_TEXT+4 and
3103 * ip->text is allocated as MAX_TEXT+2. Ok, as long as nobody
3104 * changes buff in backend() withour changing ip->text ... */
3105 strcpy(buff, ip->text);
3106 command_giver = ip->ob;
3107 trace_level = ip->trace_level;
3108 ip->chars_ready = 0; /* for escaped charmode */
3109
3110 /* Reinitialize the telnet machine, possibly already
3111 * producing the next command in .text[].
3112 */
3113 ip->tn_state = TS_DATA;
3114 telnet_neg(ip);
3115
3116 /* If the user is not in ed, don't let him issue another command
3117 * before the poll comes again.
3118 */
3119 if (ip->input_handler
3120 && ip->input_handler->type == INPUT_ED
3121 && CmdsGiven < ALLOWED_ED_CMDS)
3122 {
3123 CmdsGiven++;
3124 FD_CLR(ip->socket, &readfds);
3125 }
3126 else
3127 {
3128 DecreaseCmdGiver;
3129 CmdsGiven = 0;
3130 }
3131
3132 /* Manage snooping - should the snooper see type ahead?
3133 * Well, he doesn't here.
3134 */
3135 if (NULL != (snooper = ip->snoop_by)
3136 && !(snooper->flags & O_DESTRUCTED)
3137 && !(ip->noecho & NOECHO_REQ)
3138 )
3139 {
3140 if (O_IS_INTERACTIVE(snooper))
3141 {
3142 command_giver = snooper;
3143 add_message("%% %s\n", buff);
3144 }
3145 else
3146 {
3147 /* buff is limited to MAX_TEXT+4. Additionally,
3148 * get_message() is usually not called recursively or
3149 * from a very high stack depth, so alloca() is
3150 * probably ok. */
3151 char *snoop_message = alloca(strlen(buff) + 4);
3152 sprintf(snoop_message, "%% %s\n", buff);
3153 tell_npc_str(snooper, snoop_message);
3154 }
3155 command_giver = ip->ob;
3156 }
3157
3158 if (ip->last_time != current_time)
3159 {
3160 ip->last_time = current_time;
3161 ip->numCmds = 0;
3162 }
3163 else
3164 ip->numCmds++;
3165
3166 #ifndef SIMULATE_CHARMODE
3167 if ((ip->noecho & (CHARMODE_REQ|CHARMODE)) == CHARMODE_REQ)
3168 {
3169 DTN((" clear CHARMODE as it was refused anyway\n"));
3170 ip->noecho &= ~(CHARMODE_REQ|CHARMODE|CHARMODE_ACK);
3171 reset_input_buffer(ip);
3172 }
3173 #endif /* SIMULATE_CHARMODE */
3174
3175 DTN(("--- return with line command ---\n"));
3176 DTN(("--- '%s'\n", buff));
3177 return MY_TRUE;
3178 } /* if (have a command) */
3179
3180 } /* for (NextCmdGiver) */
3181
3182 /* If we got here, we couldn't find any commands:
3183 * loop and select (on timeout) again.
3184 */
3185
3186 } /* while(forever) */
3187
3188 /* NOTREACHED */
3189 # undef StartCmdGiver
3190 # undef DecreaseCmdGiver
3191
3192 } /* get_message() */
3193
3194 /*-------------------------------------------------------------------------*/
3195 void
3196 remove_interactive (object_t *ob, Bool force)
3197
3198 /* Remove the interactive user <ob> immediately.
3199 * If <force> is true, the user is removed under all circumstances and
3200 * without even flushing the outgoing buffer.
3201 * This function should not be called from within a LPC command execution.
3202 */
3203
3204 {
3205 object_t *save = command_giver;
3206 int i;
3207 interactive_t *interactive;
3208 object_t * curobj_save = current_object;
3209 int save_privilege;
3210
3211 interactive = O_GET_INTERACTIVE(ob);
3212
3213 /* Proper call? */
3214 for (i = 0; i < MAX_PLAYERS && all_players[i] != interactive; i++) NOOP;
3215 if (i >= MAX_PLAYERS)
3216 {
3217 fatal("Could not find and remove player %s\n", get_txt(ob->name));
3218 abort();
3219 }
3220 if (interactive->closing && !force)
3221 fatal("Double call to remove_interactive()\n");
3222
3223 interactive->closing = MY_TRUE;
3224 current_object = ob;
3225
3226 /* If the object is not destructed, save any ed buffers. */
3227
3228 if ( !(ob->flags & O_DESTRUCTED) )
3229 {
3230 command_giver = ob;
3231 abort_input_handler(interactive);
3232 }
3233
3234 save_privilege = malloc_privilege;
3235
3236 /* If the object is still not destructed, inform the master */
3237
3238 if ( !(ob->flags & O_DESTRUCTED) )
3239 {
3240 int numRemaining = interactive->text_end - interactive->command_start;
3241
3242 command_giver = NULL;
3243 current_interactive = NULL;
3244 push_ref_object(inter_sp, ob, "remove_interactive");
3245
3246 if (numRemaining > 0)
3247 {
3248 string_t * remaining = NULL;
3249 memsafe( remaining = new_n_mstring(interactive->text+interactive->command_start, numRemaining)
3250 , numRemaining, "buffer for remaining data from socket");
3251 push_string(inter_sp, remaining);
3252 }
3253 else
3254 push_ref_string(inter_sp, STR_EMPTY);
3255
3256 malloc_privilege = MALLOC_MASTER;
3257 callback_master(STR_DISCONNECT, 2);
3258 /* master might have used exec() */
3259 ob = interactive->ob;
3260 }
3261
3262 interactive->catch_tell_activ = MY_FALSE;
3263
3264 /* Untie eventual snooping relations */
3265
3266 if (interactive->snoop_by)
3267 {
3268 if (O_IS_INTERACTIVE(interactive->snoop_by))
3269 {
3270 O_GET_INTERACTIVE(interactive->snoop_by)->snoop_on = NULL;
3271 }
3272 else
3273 {
3274 free_object(interactive->snoop_by, "remove_interactive");
3275 }
3276 interactive->snoop_by = NULL;
3277 }
3278 if (interactive->snoop_on)
3279 {
3280 interactive->snoop_on->snoop_by = NULL;
3281 interactive->snoop_on = NULL;
3282 }
3283
3284 command_giver = ob;
3285
3286 #ifdef ERQ_DEMON
3287 /* If this object is disconnected because it was used to connect
3288 * a new ERQ, put the connection into place and greet the ERQ.
3289 */
3290 if (interactive->do_close & FLAG_PROTO_ERQ
3291 && interactive->socket == erq_proto_demon
3292 && !force)
3293 {
3294 static unsigned char erq_welcome[] = { IAC, TELOPT_BINARY };
3295
3296 add_message(message_flush);
3297 remove_flush_entry(interactive); /* To be sure */
3298
3299 erq_demon = interactive->socket;
3300 erq_proto_demon = -1;
3301 socket_write(erq_demon, erq_welcome, sizeof erq_welcome);
3302 }
3303 else
3304 #endif
3305 {
3306 if (!force)
3307 {
3308 /* Say goodbye to the user. */
3309 trace_level |= interactive->trace_level;
3310 add_message(message_flush);
3311 }
3312
3313 remove_flush_entry(interactive); /* To be sure */
3314
3315 #ifdef USE_MCCP
3316 if (interactive->out_compress)
3317 end_compress(interactive, MY_TRUE);
3318 /* Always force the compression end as we won't get
3319 * a second chance at it.
3320 */
3321 #endif
3322
3323 /* If there is anything left, try now. */
3324 comm_write_pending(interactive);
3325
3326 #ifdef USE_TLS
3327 tls_deinit_connection(interactive);
3328 #endif
3329 shutdown(interactive->socket, 2);
3330 socket_close(interactive->socket);
3331 } /* if (erq or user) */
3332
3333 release_host_access(interactive->access_class);
3334 /* One user less in this class */
3335
3336 num_player--;
3337
3338 /* Release all associated resources */
3339
3340 while (interactive->input_handler)
3341 {
3342 input_t * ih = interactive->input_handler;
3343
3344 interactive->input_handler = ih->next;
3345 free_input_handler(ih);
3346 }
3347
3348 if (interactive->modify_command)
3349 {
3350 free_object(interactive->modify_command, "remove_interactive");
3351 }
3352
3353 #ifdef USE_MCCP
3354 if (interactive->out_compress_buf)
3355 xfree(interactive->out_compress_buf);
3356 if (interactive->out_compress)
3357 xfree(interactive->out_compress);
3358 #endif
3359 free_svalue(&interactive->prompt);
3360
3361 if (interactive->trace_prefix)
3362 free_mstring(interactive->trace_prefix);
3363
3364 while (interactive->write_first)
3365 {
3366 struct write_buffer_s *tmp = interactive->write_first;
3367 interactive->write_first = tmp->next;
3368 xfree(tmp);
3369 }
3370
3371 /* Unlink the interactive structure from the shadow sentence
3372 * of the object.
3373 */
3374 O_GET_INTERACTIVE(ob) = NULL;
3375 check_shadow_sent(ob);
3376
3377 xfree(interactive);
3378 if (i < MAX_PLAYERS)
3379 all_players[i] = NULL;
3380 while (max_player && !all_players[max_player])
3381 max_player--;
3382 free_object(ob, "remove_interactive");
3383
3384 command_giver = check_object(save);
3385 current_object = curobj_save;
3386 malloc_privilege = save_privilege;
3387 } /* remove_interactive() */
3388
3389 /*-------------------------------------------------------------------------*/
3390 void
3391 refresh_access_data(void (*add_entry)(struct sockaddr_in *, int, long*) )
3392
3393 /* Called from access_check after the ACCESS_FILE has been (re)read, this
3394 * function has to call the passed callback function add_entry for every
3395 * user currently logged in.
3396 */
3397
3398 {
3399 interactive_t **user, *this;
3400 int n;
3401
3402 user = all_players;
3403 for (n = max_player + 2; --n; user++)
3404 {
3405 this = *user;
3406 if (this)
3407 {
3408 struct sockaddr_in addr;
3409 int port;
3410 length_t length;
3411
3412 length = sizeof(addr);
3413 getsockname(this->socket, (struct sockaddr *)&addr, &length);
3414 port = ntohs(addr.sin_port);
3415 (*add_entry)(&this->addr, port, &this->access_class);
3416 }
3417 }
3418 }
3419
3420 /*-------------------------------------------------------------------------*/
3421 static INLINE void
3422 set_default_conn_charset (char charset[32])
3423
3424 /* Set the default connection charset bitmask in <charset>.
3425 */
3426
3427 {
3428 memset(charset, 255, 32);
3429 charset['\0'/8] &= ~(1 << '\0' % 8);
3430 } /* set_default_conn_charset() */
3431
3432 /*-------------------------------------------------------------------------*/
3433 static INLINE void
3434 set_default_combine_charset (char charset[32])
3435
3436 /* Set the default combine charset bitmask in <charset>.
3437 */
3438
3439 {
3440 memset(charset, 0, 32);
3441 charset['\n'/8] &= ~(1 << '\n' % 8);
3442 charset['\0'/8] &= ~(1 << '\0' % 8);
3443 } /* set_default_combine_charset() */
3444
3445 /*-------------------------------------------------------------------------*/
3446 static void
3447 new_player ( object_t *ob, SOCKET_T new_socket
3448 , struct sockaddr_in *addr, size_t addrlen
3449 , int login_port
3450 )
3451
3452 /* Accept (or reject) a new connection on <new_socket> from <addr> (length
3453 * of structure is <addrlen>), accepted on port <login_port>.
3454 *
3455 * Called when get_message() detects a new connection on one of the
3456 * login ports, this function checks if the user may access the mud.
3457 *
3458 * If yes and <ob> is NULL, a new interactive structure is generated and
3459 * bound to the master, then master->connect() is called. This call is
3460 * expected to return an object and the interactive structure is rebound to
3461 * that object.
3462 * If yes and <ob> is an object, a new interactive structure is generated
3463 * and bound to <ob>
3464 *
3465 * Finally, logon() is called in the newly-interactive object.
3466 * Alternatively if no <ob> is given, master->connect() may exec() the
3467 * connection away from the master, in which case no further action will be
3468 * taken after the return from that call.
3469 *
3470 * If the connection can't be accepted for some reason, a failure
3471 * message will be send back to the user and the socket will be
3472 * closed.
3473 */
3474
3475 {
3476 int i; /* Index of free slot in all_players[] */
3477 char *message; /* Failure message */
3478 svalue_t *ret; /* LPC call results */
3479 interactive_t *new_interactive;
3480 /* The new interactive structure */
3481 long class; /* Access class */
3482
3483 /* Set some useful socket options */
3484 set_socket_nonblocking(new_socket);
3485 set_close_on_exec(new_socket);
3486 set_socket_own(new_socket);
3487
3488 /* Check for access restrictions for this connection */
3489 message = allow_host_access(addr, login_port, &class);
3490
3491 if (access_log != NULL)
3492 {
3493 FILE *log_file = fopen (access_log, "a");
3494
3495 if (log_file) {
3496 FCOUNT_WRITE(log_file);
3497 fprintf(log_file, "%s %s: %s\n"
3498 , time_stamp()
3499 #ifndef USE_IPV6
3500 , inet_ntoa(addr->sin_addr)
3501 #else
3502 , inet6_ntoa(addr->sin_addr)
3503 #endif
3504 , message ? "denied" : "granted");
3505 fclose(log_file);
3506 }
3507 }
3508
3509 if (message)
3510 {
3511 socket_write(new_socket, message, strlen(message));
3512 socket_write(new_socket, "\r\n", 2);
3513 socket_close(new_socket);
3514 return;
3515 }
3516
3517 if (d_flag)
3518 debug_message("%s New player at socket %d.\n"
3519 , time_stamp(), new_socket);
3520
3521 /* Look for an empty slot in all_players[] */
3522 for (i = 0; i < MAX_PLAYERS && all_players[i] != NULL; i++) NOOP;
3523 if (i >= MAX_PLAYERS)
3524 {
3525 /* calling closures here would need special error handling */
3526 if (driver_hook[H_NO_IPC_SLOT].type == T_STRING)
3527 {
3528 string_t *msg;
3529
3530 msg = driver_hook[H_NO_IPC_SLOT].u.str;
3531 socket_write(new_socket, get_txt(msg), mstrsize(msg));
3532 }
3533 else
3534 {
3535 message = "The mud is full. Come back later.\r\n";
3536 socket_write(new_socket, message, strlen(message));
3537 }
3538 socket_close(new_socket);
3539 debug_message("%s Out of IPC slots for new connection.\n"
3540 , time_stamp());
3541 return;
3542 }
3543
3544 /* The master must be loaded and free to accept a login */
3545 assert_master_ob_loaded();
3546 if (O_IS_INTERACTIVE(master_ob))
3547 {
3548 message = "Cannot accept connections. Come back later.\r\n";
3549 socket_write(new_socket, message, strlen(message));
3550 socket_close(new_socket);
3551 debug_message("%s Master still busy with previous new connection.\n"
3552 , time_stamp());
3553 return;
3554 }
3555
3556 command_giver = master_ob;
3557 trace_level = 0;
3558 new_interactive = xalloc(sizeof (interactive_t));
3559 if (!new_interactive)
3560 {
3561 message = "Cannot accept connection (out of memory). Come back later.\r\n";
3562 socket_write(new_socket, message, strlen(message));
3563 socket_close(new_socket);
3564 debug_message("%s Out of memory (%zu bytes) for new connection.\n"
3565 , time_stamp(), sizeof(interactive_t));
3566 return;
3567 }
3568
3569 if (ob && O_IS_INTERACTIVE(ob))
3570 {
3571 /* The caller provided an object to connect to. But since
3572 * it is already interactive, we have to terminate that
3573 * old connection.
3574 */
3575 remove_interactive(ob, MY_FALSE);
3576 }
3577
3578 /* Link the interactive to the master */
3579
3580 assert_shadow_sent(master_ob);
3581 O_GET_INTERACTIVE(master_ob) = new_interactive;
3582 master_ob->flags |= O_ONCE_INTERACTIVE;
3583 new_interactive->ob = ref_object(master_ob, "new_player");
3584 new_interactive->outgoing_conn = (ob != NULL);
3585
3586 /* Initialize the rest of the interactive structure */
3587
3588 #ifdef USE_MCCP
3589 new_interactive->compressing = 0;
3590 new_interactive->out_compress = NULL;
3591 new_interactive->out_compress_buf=NULL;
3592 #endif
3593 #ifdef USE_TLS
3594 new_interactive->tls_status = TLS_INACTIVE;
3595 new_interactive->tls_session = NULL;
3596 new_interactive->tls_cb = NULL;
3597 #endif
3598 new_interactive->input_handler = NULL;
3599 put_number(&new_interactive->prompt, 0);
3600 new_interactive->modify_command = NULL;
3601 new_interactive->closing = MY_FALSE;
3602 new_interactive->tn_enabled = MY_TRUE;
3603 new_interactive->do_close = 0;
3604 new_interactive->noecho = 0;
3605 new_interactive->supress_go_ahead = MY_FALSE;
3606 new_interactive->gobble_char = 0;
3607 new_interactive->catch_tell_activ = MY_TRUE;
3608 new_interactive->text_end = 0;
3609 new_interactive->command_start = 0;
3610 new_interactive->command_end = 0;
3611 new_interactive->chars_ready = 0;
3612 new_interactive->save_tn_state = TS_INVALID;
3613 new_interactive->tn_start = 0;
3614 new_interactive->tn_end = 0;
3615 new_interactive->tn_state = TS_DATA;
3616 new_interactive->ts_data = TS_DATA;
3617 new_interactive->snoop_on = NULL;
3618 new_interactive->snoop_by = NULL;
3619 new_interactive->last_time = current_time;
3620 new_interactive->numCmds = 0;
3621 new_interactive->maxNumCmds = -1;
3622 new_interactive->trace_level = 0;
3623 new_interactive->trace_prefix = NULL;
3624 new_interactive->message_length = 0;
3625 new_interactive->quote_iac = MY_TRUE;
3626 set_default_conn_charset(new_interactive->charset);
3627 set_default_combine_charset(new_interactive->combine_cset);
3628 new_interactive->text[0] = '\0';
3629 memcpy(&new_interactive->addr, addr, addrlen);
3630 new_interactive->access_class = class;
3631 new_interactive->socket = new_socket;
3632 new_interactive->next_player_for_flush = NULL;
3633 new_interactive->previous_player_for_flush = NULL;
3634 new_interactive->msg_discarded = DM_NONE;
3635
3636 new_interactive->write_first = new_interactive->write_last = NULL;
3637 new_interactive->write_size = 0;
3638 new_interactive->write_max_size = -2;
3639
3640 /* Add the new interactive structure to the list of users */
3641
3642 all_players[i] = new_interactive;
3643 if (i > max_player)
3644 max_player = i;
3645 num_player++;
3646
3647 current_interactive = master_ob;
3648
3649 if (!ob)
3650 {
3651 /* The caller did not provide an object to connect to.
3652 * Call master->connect() and evaluate the result.
3653 */
3654 ret = callback_master(STR_CONNECT, 0);
3655 if (new_interactive != O_GET_INTERACTIVE(master_ob))
3656 return;
3657 if (ret == NULL
3658 || ret->type != T_OBJECT
3659 || (ob = ret->u.ob, O_IS_INTERACTIVE(ob)))
3660 {
3661 remove_interactive(master_ob, MY_FALSE);
3662 return;
3663 }
3664 command_giver = master_ob;
3665 add_message(message_flush);
3666 }
3667
3668 /* ob is now a non-interactive object, either passed in from the caller
3669 * or returned from connect().
3670 * Relink the interactive from the master to this as the user object.
3671 */
3672
3673 O_GET_INTERACTIVE(master_ob) = NULL;
3674 master_ob->flags &= ~O_ONCE_INTERACTIVE;
3675 check_shadow_sent(master_ob);
3676 free_object(master_ob, "new_player");
3677
3678 assert_shadow_sent(ob);
3679 O_GET_INTERACTIVE(ob) = new_interactive;
3680 new_interactive->ob = ref_object(ob, "new_player");
3681 ob->flags |= O_ONCE_INTERACTIVE;
3682
3683 /* Prepare to call logon() in the new user object.
3684 */
3685 command_giver = ob;
3686 current_interactive = ob;
3687 if (new_interactive->snoop_on)
3688 {
3689 new_interactive->snoop_on->snoop_by = ob;
3690 }
3691 #ifdef ERQ_DEMON
3692 (void) lookup_ip_entry(new_interactive->addr.sin_addr, MY_TRUE);
3693 /* TODO: We could pass the retrieved hostname right to login */
3694 #endif
3695 #ifdef USE_TLS
3696 /* If we're using secure connections and the connect() triggered
3697 * a handshake which is still going on, we call logon() as
3698 * the default TLS callback. This way, logon() is callled only
3699 * if the connection could be established, secure or not.
3700 */
3701 if (new_interactive->tls_status != TLS_HANDSHAKING)
3702 {
3703 /* Connection not secure, or already established: logon. */
3704 logon_object(ob);
3705 }
3706 else if (new_interactive->tls_cb == NULL)
3707 {
3708 callback_t * cb;
3709
3710 /* Connection in TLS handshake, but not callback: set a callback
3711 * to the logon function.
3712 */
3713 if (find_function(STR_LOGON, current_interactive->prog) < 0)
3714 {
3715 errorf("Could not find %s() on the player %s\n", get_txt(STR_LOGON), get_txt(current_interactive->name));
3716 /* NOTREACHED */
3717 }
3718
3719 xallocate(cb, sizeof(*cb), "logon tls-callback structure");
3720 setup_function_callback(cb, current_interactive, STR_LOGON, 0, NULL, MY_TRUE);
3721 new_interactive->tls_cb = cb;
3722
3723 }
3724 /* else: Connection in TLS handshake and callback set by connect(). */
3725 #else
3726 logon_object(ob);
3727 #endif /* USE_TLS */
3728 if (!(ob->flags & O_DESTRUCTED))
3729 print_prompt();
3730 flush_all_player_mess();
3731 } /* new_player() */
3732
3733 /*-------------------------------------------------------------------------*/
3734 void
3735 set_noecho (interactive_t *ip, char noecho, Bool local_change, Bool external)
3736
3737 /* Change the input mode <i>->noecho to the given <noecho>, performing all
3738 * necessary telnet negotiations. If the driverhook H_NOECHO is set,
3739 * the hook function is expected to do all the negotiations.
3740 * If <local_change> is TRUE, the driver will not send out any telnet
3741 * commands for CHARMODE/LINEMODE changes.
3742 */
3743
3744 {
3745 char old, confirm;
3746 object_t *ob;
3747
3748 if (!ip->tn_enabled)
3749 {
3750 DTN(("set_noecho(%02hhx) old %02hhx: TN disabled\n"
3751 , noecho, ip->noecho));
3752 }
3753
3754 old = ip->noecho;
3755
3756 confirm = (char)(
3757 noecho | CHARMODE_REQ_TO_CHARMODE(noecho & (NOECHO_REQ|CHARMODE_REQ)));
3758 DTN(("set_noecho(%02hhx%s) old %02hhx %s\n"
3759 , noecho, local_change ? " local" : "", old, decode_noecho(old)));
3760 DTN((" -> confirm: %02hhx %s\n"
3761 , confirm, decode_noecho(confirm)));
3762 DTN((" -> %02hhx %s\n"
3763 , confirm | NOECHO_ACKSHIFT(confirm)
3764 , decode_noecho(confirm | NOECHO_ACKSHIFT(confirm))
3765 ));
3766
3767 ip->noecho = confirm;
3768
3769 confirm |= NOECHO_ACKSHIFT(confirm);
3770 if (((confirm ^ old) & (NOECHO_MASK|CHARMODE_MASK)) && ip->tn_enabled )
3771 {
3772 DTN(("set_noecho(): Mode changes\n"));
3773 ob = ip->ob;
3774 if (!(ob->flags & O_DESTRUCTED))
3775 {
3776 if (driver_hook[H_NOECHO].type == T_STRING
3777 || driver_hook[H_NOECHO].type == T_CLOSURE
3778 )
3779 {
3780 DTN(("set_noecho(): calling H_NOECHO\n"));
3781 push_number(inter_sp, noecho);
3782 push_ref_valid_object(inter_sp, ob, "set_no_echo");
3783 push_number(inter_sp, local_change ? 1 : 0);
3784 if (driver_hook[H_NOECHO].type == T_STRING)
3785 secure_apply_ob(driver_hook[H_NOECHO].u.str, ob, 3, external);
3786 else
3787 {
3788 if (driver_hook[H_NOECHO].x.closure_type == CLOSURE_LAMBDA)
3789 {
3790 free_object(driver_hook[H_NOECHO].u.lambda->ob
3791 , "set_noecho");
3792 driver_hook[H_NOECHO].u.lambda->ob
3793 = ref_object(ob, "set_noecho");
3794 }
3795 secure_call_lambda(&driver_hook[H_NOECHO], 3, external);
3796 }
3797 if (~confirm & old & CHARMODE_MASK)
3798 {
3799 if (ip->save_tn_state != TS_INVALID)
3800 {
3801 DT(("'%s' set_noecho(): 0 chars ready, "
3802 "saved state %hhd\n", get_txt(ip->ob->name)
3803 , ip->save_tn_state));
3804 ip->chars_ready = 0;
3805 ip->tn_state = ip->save_tn_state;
3806 }
3807 reset_input_buffer(ip);
3808 }
3809 }
3810 else
3811 {
3812 object_t *save;
3813
3814 save = command_giver;
3815 command_giver = ob;
3816 #ifdef SAVE_NOECHO
3817 ip->noecho &= ~NOECHO_DELAYED;
3818 #endif
3819 if (~confirm & old & NOECHO)
3820 {
3821 DTN(("set_noecho(): WONT TELOPT_ECHO\n"));
3822 send_wont(TELOPT_ECHO);
3823 }
3824 else if (confirm & ~old & NOECHO_MASK)
3825 {
3826 #ifdef SAVE_NOECHO
3827 if (confirm & ~old & CHARMODE_MASK)
3828 {
3829 ip->noecho |= NOECHO_DELAYED;
3830 ip->noecho &= ~(NOECHO | NOECHO_REQ);
3831 DTN(("set_noecho(): delaying WILL TELOPT_ECHO\n"));
3832 }
3833 else
3834 {
3835 #endif
3836 DTN(("set_noecho(): WILL TELOPT_ECHO\n"));
3837 send_will(TELOPT_ECHO);
3838 #ifdef SAVE_NOECHO
3839 }
3840 #endif
3841 }
3842 else /* No change in NOECHO mode */ if (confirm & NOECHO)
3843 {
3844 /* Since we stay in NOECHO mode, we need the ACK flag set. */
3845 DTN(("set_noecho(): Staying in NOECHO mode\n"));
3846 ip->noecho |= NOECHO_ACKSHIFT(NOECHO);
3847 }
3848
3849 if (ip->supress_go_ahead && !(confirm & (NOECHO|CHARMODE)))
3850 {
3851 DTN(("set_noecho(): WONT TELOPT_SGA\n"));
3852 ip->supress_go_ahead = MY_FALSE;
3853 send_wont(TELOPT_SGA);
3854 }
3855 /* Only using SGA for charmode is supported hardcoded.
3856 * To make more sophisticated negotiations, e.g. using LINEMODE,
3857 * use the H_NOECHO hook.
3858 */
3859 if ((~confirm & old & CHARMODE_MASK)
3860 || ((~confirm & old & NOECHO_STALE) && (old & CHARMODE_MASK))
3861 )
3862 {
3863 if(~confirm & old & CHARMODE_MASK)
3864 {
3865 DTN(("set_noecho(): turn off charmode\n"));
3866 if ((old & CHARMODE) && !local_change)
3867 {
3868 DTN(("set_noecho(): DONT TELOPT_SGA\n"));
3869 send_dont(TELOPT_SGA);
3870 }
3871 if (ip->save_tn_state != TS_INVALID)
3872 {
3873 DTN(("set_noecho(): 0 chars ready, saved state %hhd\n", ip->save_tn_state));
3874 ip->chars_ready = 0;
3875 ip->tn_state = ip->save_tn_state;
3876 }
3877 }
3878
3879 reset_input_buffer(ip);
3880 }
3881 else if (confirm & ~old & CHARMODE_MASK)
3882 {
3883 DTN(("set_noecho(): turn on charmode\n"));
3884 if (!local_change)
3885 {
3886 DTN(("set_noecho(): DO+WILL TELOPT_SGA\n"));
3887 send_do(TELOPT_SGA);
3888 /* some telnet implementations (Windows' telnet is one) mix
3889 * up DO and WILL SGA, thus we send WILL SGA as well.
3890 */
3891 send_will(TELOPT_SGA);
3892 ip->supress_go_ahead = MY_TRUE;
3893 }
3894 else
3895 /* Since there won't be any telnet negotiation
3896 * we can assume that CHARMODE is acknowledged.
3897 */
3898 ip->noecho |= NOECHO_ACKSHIFT(CHARMODE);
3899
3900 }
3901 else /* No change in CHARMODE mode */ if (confirm & CHARMODE)
3902 {
3903 /* Since we stay in CHARMODE mode, we need the ACK flag set. */
3904 DTN(("set_noecho(): Staying in CHARMODE mode\n"));
3905 ip->noecho |= NOECHO_ACKSHIFT(CHARMODE);
3906 }
3907
3908 command_giver = save;
3909 }
3910 } /* if (!(ob->flags & O_DESTRUCTED)) */
3911 }
3912 else
3913 {
3914 /* No change in modes.
3915 * However, if we stay in NOECHO/CHARMODE, we need to set
3916 * the ACK flags.
3917 */
3918 if (confirm & CHARMODE)
3919 {
3920 /* Since we stay in CHARMODE mode, we need the ACK flag set. */
3921 DTN(("set_noecho(): Staying in CHARMODE mode\n"));
3922 ip->noecho |= NOECHO_ACKSHIFT(CHARMODE);
3923 }
3924 if (confirm & NOECHO)
3925 {
3926 /* Since we stay in NOECHO mode, we need the ACK flag set. */
3927 DTN(("set_noecho(): Staying in NOECHO mode\n"));
3928 ip->noecho |= NOECHO_ACKSHIFT(NOECHO);
3929 }
3930 }
3931
3932 } /* set_noecho() */
3933
3934 /*-------------------------------------------------------------------------*/
3935 int
3936 find_no_bang (interactive_t *ip)
3937
3938 /* Find the most recent input_to in *<ip> which specified "IGNORE_BANG" and
3939 * return its full "noecho" flags. This may be the ip->noecho itself!
3940 * If there is none, return 0.
3941 */
3942
3943 {
3944 input_t *ih;
3945
3946 if (ip->noecho & IGNORE_BANG)
3947 return ip->noecho;
3948
3949 for (ih = ip->input_handler; ih; ih = ih->next)
3950 if (ih->noecho & IGNORE_BANG)
3951 return ih->noecho;
3952 return 0;
3953 } /* find_no_bang() */
3954
3955 /*-------------------------------------------------------------------------*/
3956 static Bool
3957 call_input_to (interactive_t *i, char *str, input_to_t *it)
3958
3959 /* Call the input_to handler <it> for this user <i> and the input <str>.
3960 * Return TRUE if this handler was executed successfully, and FALSE
3961 * if the input was not processed.
3962 *
3963 * This function is only called by call_function_interactive().
3964 */
3965
3966 {
3967 static input_to_t current_it;
3968 /* Current input_to, static so that longjmp() won't clobber it. */
3969
3970 struct error_recovery_info error_recovery_info;
3971 object_t *ob; /* object holding <function> */
3972
3973
3974 /* We got the right input_to_t. Check if it's still valid. */
3975 ob = callback_object(&(it->fun));
3976 if (!ob)
3977 {
3978 /* Sorry, the object has selfdestructed ! */
3979 free_input_to(it);
3980 return MY_FALSE;
3981 }
3982
3983 if (O_PROG_SWAPPED(ob)
3984 && load_ob_from_swap(ob) < 0)
3985 {
3986 free_input_to(it);
3987 errorf("Out of memory: unswap object '%s'.\n", get_txt(ob->name));
3988 return MY_FALSE;
3989 }
3990
3991 /* Clear the input_to() reference in case the function called
3992 * sets up a new one.
3993 */
3994 current_it = *it;
3995 xfree(it);
3996 free_svalue(¤t_it.input.prompt); /* Don't need this anymore */
3997
3998 /* Activate the local error recovery context */
3999
4000 error_recovery_info.rt.last = rt_context;
4001 error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
4002 rt_context = (rt_context_t *)&error_recovery_info.rt;
4003
4004 if (setjmp(error_recovery_info.con.text))
4005 {
4006 /* An error occured: free the remaining data,
4007 * restore the error stack and return
4008 */
4009
4010 clear_state();
4011 debug_message("%s Error in input_to().\n", time_stamp());
4012 free_callback(&(current_it.fun));
4013 rt_context = error_recovery_info.rt.last;
4014 return MY_TRUE;
4015 }
4016
4017 /* Call the input_to() function with the newly input string */
4018
4019 push_c_string(inter_sp, str);
4020 (void)backend_callback(&(current_it.fun), 1);
4021
4022 rt_context = error_recovery_info.rt.last;
4023
4024 /* Done */
4025 return MY_TRUE;
4026 }
4027
4028 /*-------------------------------------------------------------------------*/
4029 Bool
4030 call_function_interactive (interactive_t *i, char *str)
4031
4032 /* Execute a pending input handler for this user <i> and the input <str>
4033 * Return TRUE if an input_to() or ed() was pending and executed, and FALSE
4034 * if the input was not processed.
4035 *
4036 * This function is called by the backend as part of the input processing.
4037 */
4038
4039 {
4040 input_t *ih;
4041 ih = i->input_handler;
4042
4043 /* _Are_ there an input_to() pending? */
4044 if (!ih)
4045 return MY_FALSE;
4046
4047 /* Yes, there are. Check if we have to handle input escape. */
4048 if (*str == input_escape && str[1])
4049 {
4050 input_t * prev;
4051
4052 for (prev = NULL
4053 ; ih && !(ih->noecho & IGNORE_BANG)
4054 ; prev = ih, ih = ih->next)
4055 NOOP;
4056
4057 if (ih)
4058 {
4059 /* Move this 'IGNORE_BANG' input_to to the top of list
4060 * since it's the one we're going to execute.
4061 */
4062 if (prev)
4063 {
4064 prev->next = ih->next;
4065 ih->next = i->input_handler;
4066 i->input_handler = ih;
4067 }
4068
4069 if (!(i->noecho & NOECHO) != !(ih->noecho & NOECHO_REQ)) {
4070 /* !message for ECHO-context while in NOECHO - simulate the
4071 * echo by sending the (remaining) raw data we got.
4072 */
4073 add_message("%s\n", str + i->chars_ready);
4074 i->chars_ready = 0;
4075 }
4076
4077 /* Don't hide the leading input escape */
4078 }
4079 else
4080 {
4081 /* Bang-input but no matching input_to(): return */
4082 return MY_FALSE;
4083 }
4084 }
4085
4086 switch (ih->type)
4087 {
4088 case INPUT_TO:
4089 {
4090 Bool res;
4091
4092 i->input_handler = ih->next;
4093
4094 /* if there is a series of noecho/charmode input, we should only
4095 * negotiate when we know that the state actually should change.
4096 * In other words: should the input_to function request NOECHO
4097 * again, the NOECHO_STALE bit will be cleared and we will not
4098 * turn NOECHO off after the call.
4099 */
4100 if (i->noecho)
4101 {
4102 i->noecho |= NOECHO_STALE;
4103 }
4104
4105 res = call_input_to(i, str, (input_to_t*) ih);
4106
4107 /* If NOECHO is no longer needed, turn it off. */
4108
4109 if (i->noecho & NOECHO_STALE)
4110 {
4111 set_noecho(i, i->input_handler ? i->input_handler->noecho : 0
4112 , i->input_handler ? i->input_handler->local : MY_FALSE
4113 , MY_TRUE);
4114 }
4115
4116 return res;
4117 }
4118
4119 case INPUT_ED:
4120 ed_cmd(str, ih);
4121 return MY_TRUE;
4122 }
4123
4124 return MY_FALSE;
4125
4126 } /* call_function_interactive() */
4127
4128 /*-------------------------------------------------------------------------*/
4129 static Bool
4130 set_call ( object_t *ob, input_to_t *it, char noecho
4131 , Bool local_change, Bool append)
4132
4133 /* Set a a new input_to <it> with the flags <noecho> (mainly really NOECHO,
4134 * but also IGNORE_BANG or not) to the interactive object <ob>.
4135 * If <local_change> is TRUE, the driver will not send out any telnet
4136 * commands for CHARMODE/LINEMODE changes.
4137 * If <append> is TRUE, the call is appended to the list of existing
4138 * input_to's, if any.
4139 * Return TRUE on success.
4140 *
4141 * Called for efun input_to().
4142 */
4143
4144 {
4145 interactive_t *ip;
4146
4147 if (ob == NULL || it == NULL)
4148 return MY_FALSE;
4149 if (!(O_SET_INTERACTIVE(ip, ob))
4150 || ip->closing
4151 )
4152 {
4153 return MY_FALSE;
4154 }
4155
4156 if (!append && ip->input_handler != NULL)
4157 {
4158 input_t * ih = ip->input_handler;
4159
4160 while (ih && ih->type != INPUT_TO)
4161 ih = ih->next;
4162
4163 if (ih && ((input_to_t*)ih)->eval_nr == eval_number)
4164 return MY_FALSE;
4165 }
4166
4167 it->input.noecho = noecho;
4168 it->input.local = local_change;
4169 it->input.type = INPUT_TO;
4170
4171 /* Appended input_tos never count. */
4172 it->eval_nr = eval_number - (append ? 1 : 0);
4173
4174 add_input_handler(ip, &(it->input), append);
4175 return MY_TRUE;
4176 } /* set_call() */
4177
4178 /*-------------------------------------------------------------------------*/
4179 void
4180 remove_all_players (void)
4181
4182 /* Destruct all user objects. This is first tried by calling master->remove()
4183 * for every object. If this doesn't destruct the user object,
4184 * destruct() is used.
4185 * The function is called when the game is shut down.
4186 */
4187
4188 {
4189 int i;
4190
4191 for (i = 0; i < MAX_PLAYERS; i++) {
4192 if (all_players[i] == 0 || (all_players[i]->ob->flags & O_DESTRUCTED))
4193 continue;
4194 command_giver = all_players[i]->ob;
4195 trace_level |= all_players[i]->trace_level;
4196 RESET_LIMITS;
4197 CLEAR_EVAL_COST;
4198 push_ref_object(inter_sp, all_players[i]->ob, "remove_all_players");
4199 (void)callback_master(STR_REMOVE_PL, 1);
4200 if ( !(all_players[i]->ob->flags & O_DESTRUCTED) ) {
4201 destruct(all_players[i]->ob);
4202 }
4203 }
4204 }
4205
4206 /*-------------------------------------------------------------------------*/
4207 static void
4208 print_prompt_string (string_t *prompt)
4209
4210 /* Print the string <prompt> to the current command_giver.
4211 * This function checks if the driver hook H_PRINT_PROMPT is set and in that
4212 * case passes the string through the set function. If it is not set,
4213 * the prompt is printed via add_message().
4214 #ifdef USE_TLS
4215 * The prompt is not printed at all if the interactive is currently
4216 * negotiating the TLS handshake.
4217 #endif
4218 */
4219
4220 {
4221 svalue_t *hook = &driver_hook[H_PRINT_PROMPT];
4222
4223 #ifdef USE_TLS
4224 {
4225 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4226 if (NULL != ip && TLS_HANDSHAKING == ip->tls_status)
4227 return;
4228 }
4229 #endif /* USE_TLS */
4230
4231 if (hook->type == T_CLOSURE)
4232 {
4233 object_t *ob;
4234
4235 /* Needed for clean error recovery */
4236
4237 previous_ob = 0;
4238 current_object = command_giver;
4239
4240 /* Check if the object the closure is bound to still exists.
4241 * If not, erase the hook, print the prompt using add_message(),
4242 * then throw an error.
4243 */
4244 ob = !CLOSURE_MALLOCED(hook->x.closure_type)
4245 ? hook->u.ob
4246 : hook->u.lambda->ob;
4247
4248 if (ob->flags & O_DESTRUCTED)
4249 {
4250 free_svalue(hook);
4251 put_number(hook, 0);
4252 current_object = NULL; /* So that catch_tell() can see it */
4253 add_message(FMT_STRING, prompt);
4254 errorf("H_PRINT_PROMPT for %s was a closure bound to a "
4255 "now-destructed object - hook removed.\n",
4256 get_txt(command_giver->name));
4257 /* NOTREACHED */
4258 }
4259
4260 push_ref_string(inter_sp, prompt);
4261 call_lambda(hook, 1);
4262 free_svalue(inter_sp--);
4263 }
4264 else if (hook->type == T_STRING)
4265 {
4266 push_ref_string(inter_sp, prompt);
4267 (void)sapply(hook->u.str, command_giver, 1);
4268 }
4269 else
4270 {
4271 current_object = NULL; /* So that catch_tell() can see it */
4272 add_message(FMT_STRING, prompt);
4273 }
4274 } /* print_prompt_string() */
4275
4276 /*-------------------------------------------------------------------------*/
4277 void
4278 print_prompt (void)
4279
4280 /* Print the prompt of the current command_giver, unless disabled
4281 * by input_to. If the prompt is set to a closure, the closure
4282 * is called and expected to return the actual prompt string or
4283 * to print the prompt itself.
4284 */
4285
4286 {
4287 interactive_t *ip;
4288 svalue_t *prompt = NULL;
4289 object_t * save_current = current_object;
4290 object_t * save_previous = previous_ob;
4291 Bool usingDefaultPrompt = MY_FALSE;
4292
4293 #ifdef DEBUG
4294 if (command_giver == 0)
4295 fatal("command_giver == 0.\n");
4296 #endif
4297
4298 if (!(O_SET_INTERACTIVE(ip, command_giver)))
4299 fatal("print_prompt() of non-interactive object\n");
4300
4301 if (ip->input_handler != NULL)
4302 {
4303 prompt = &ip->input_handler->prompt;
4304 }
4305 else
4306 {
4307 prompt = &ip->prompt;
4308 if (prompt->type != T_CLOSURE && prompt->type != T_STRING)
4309 {
4310 prompt = &driver_hook[H_DEFAULT_PROMPT];
4311 usingDefaultPrompt = MY_TRUE;
4312 }
4313 }
4314
4315 if (prompt->type == T_CLOSURE)
4316 {
4317 object_t *ob;
4318
4319 /* Needed for clean error recovery */
4320
4321 previous_ob = 0;
4322 current_object = command_giver;
4323
4324 /* Check if the object the closure is bound to still exists.
4325 * If not, restore the prompt to the default (this also works with
4326 * the default prompt driver hook), then throw an error.
4327 */
4328 ob = !CLOSURE_MALLOCED(prompt->x.closure_type)
4329 ? prompt->u.ob
4330 : prompt->u.lambda->ob;
4331
4332 if (ob && ob->flags & O_DESTRUCTED)
4333 {
4334 free_svalue(prompt);
4335 put_ref_string(prompt, STR_DEFAULT_PROMPT);
4336 print_prompt_string(prompt->u.str);
4337 errorf("Prompt of %s was a closure bound to a now-destructed "
4338 "object - default prompt restored.\n",
4339 get_txt(command_giver->name));
4340 /* NOTREACHED */
4341 }
4342
4343 call_lambda(prompt, 0);
4344 prompt = inter_sp;
4345 if (prompt->type != T_STRING)
4346 {
4347 free_svalue(prompt);
4348 }
4349 else
4350 {
4351 /* beware: print_prompt_string() might cause an error.
4352 * Thus, the LPC stack has to include the prompt to free it then.
4353 */
4354 print_prompt_string(prompt->u.str);
4355 free_svalue(prompt);
4356 }
4357 inter_sp--;
4358 }
4359 else if (prompt->type == T_STRING)
4360 {
4361 print_prompt_string(prompt->u.str);
4362 }
4363 else if (usingDefaultPrompt)
4364 {
4365 /* No prompt nor default prompt given, and it's not an input_to:
4366 * print the usual prompt.
4367 */
4368 print_prompt_string(STR_DEFAULT_PROMPT);
4369 }
4370
4371 current_object = save_current;
4372 previous_ob = save_previous;
4373 } /* print_prompt() */
4374
4375 /*-------------------------------------------------------------------------*/
4376 static int
4377 set_snoop (object_t *me, object_t *you)
4378
4379 /* Set a snoop from <me> on the IO of <you>. If <you> is NULL, an
4380 * existing snoop is terminated. <me> need not to be an interactive
4381 * user.
4382 *
4383 * Return 1 on success, -1 if a snooping loop would be caused, 0 for
4384 * any other failure.
4385 *
4386 * The function calls master->valid_snoop() to test if the snoop
4387 * is allowed.
4388 */
4389
4390 {
4391 interactive_t *on = NULL; /* interactive struct of <you> */
4392 interactive_t *by = NULL; /* interactive struct of <me> */
4393 interactive_t *tmp;
4394 svalue_t *ret;
4395
4396 /* Stop if people managed to quit before we got this far */
4397 if (me->flags & O_DESTRUCTED)
4398 return 0;
4399 if (you && (you->flags & O_DESTRUCTED))
4400 return 0;
4401
4402 /* Check for permissions with valid_snoop in master */
4403 push_ref_object(inter_sp, me, "snoop");
4404 if (you == NULL)
4405 push_number(inter_sp, 0);
4406 else
4407 push_ref_object(inter_sp, you, "snoop");
4408 ret = apply_master(STR_VALID_SNOOP, 2);
4409
4410 if (!ret || ret->type != T_NUMBER || ret->u.number == 0)
4411 return 0;
4412
4413 if (me->flags & O_DESTRUCTED)
4414 return 0;
4415
4416 /* Test is <me> is able to snoop anyway.
4417 * Set <by> to <me>'s interactive struct if yes.
4418 */
4419 if (O_SET_INTERACTIVE(by, me) && by->closing)
4420 return 0;
4421
4422 if (you)
4423 {
4424 /* Test if <you> can be snooped at all.
4425 * Set <on> to <you>'s interactive struct if yes.
4426 */
4427 if (you->flags & O_DESTRUCTED)
4428 return 0;
4429 if (!(O_SET_INTERACTIVE(on, you)) || on->closing)
4430 return 0;
4431 }
4432 else
4433 {
4434 /* Stop snoop.
4435 * For this, set <on> to the interactive struct of the snoops
4436 * victim. If <by> is NULL, <me> is propably a netdead user
4437 * or a NPC and we have to scan the list of users for the victim.
4438 */
4439
4440 if (!by)
4441 {
4442 int i;
4443
4444 for (i = max_player+1;;)
4445 {
4446 if (--i < 0)
4447 return 0;
4448 if (NULL != (on = all_players[i]) && on->snoop_by == me)
4449 break;
4450 }
4451 if (on->closing)
4452 return 0;
4453 free_object(me, "set_snoop");
4454 }
4455 else
4456 {
4457 on = by->snoop_on;
4458 if (!on || on->closing)
4459 return 0;
4460 by->snoop_on = NULL;
4461 }
4462 on->snoop_by = NULL;
4463 return 1;
4464 }
4465
4466 /* If we come here, a snoop on <you> by <me> is possible.
4467 * Now protect against snooping loops.
4468 */
4469
4470 for (tmp = on; tmp; tmp = tmp->snoop_on)
4471 {
4472 if (tmp == by)
4473 return -1;
4474 }
4475
4476 /* Terminate previous snoop, if any */
4477 if (on->snoop_by)
4478 {
4479 interactive_t *ip;
4480
4481 if (O_SET_INTERACTIVE(ip, on->snoop_by))
4482 {
4483 if (ip->closing)
4484 return 0;
4485 ip->snoop_on = 0;
4486 }
4487 else
4488 {
4489 free_object(on->snoop_by, "set_snoop");
4490 }
4491 on->snoop_by = NULL;
4492 }
4493
4494 /* Initialise the new snoop */
4495 if (by)
4496 {
4497 if (by->snoop_on)
4498 {
4499 if (by->snoop_on->closing)
4500 return 0;
4501 by->snoop_on->snoop_by = 0;
4502 by->snoop_on = 0;
4503 }
4504 by->snoop_on = on;
4505 }
4506 else
4507 {
4508 ref_object(me, "set_snoop");
4509 }
4510
4511 on->snoop_by = me;
4512 return 1;
4513 } /* set_snoop() */
4514
4515 /*=========================================================================*/
4516 /* Telnet Support
4517 */
4518
4519 /* Note: when stored in char variables, IAC can be equal to EOF.
4520 * This can cause sprintf(), which is used in add_message(), to abort
4521 * output after EOF. Therefore, don't try to send anything after the IAC
4522 * in the same call to add_message().
4523 */
4524
4525 /*-------------------------------------------------------------------------*/
4526 static INLINE void
4527 send_telnet_option (char action, char option)
4528
4529 /* Send IAC <action> <option> */
4530
4531 {
4532 char msg[3];
4533
4534 msg[0] = IAC;
4535 msg[1] = action;
4536 msg[2] = option;
4537 SEND_TELNET_COMMAND(
4538 add_message(FMT_BINARY, msg, 3);
4539 add_message(message_flush);
4540 )
4541 } /* send_telnet_option() */
4542
4543 /*-------------------------------------------------------------------------*/
4544 static void
4545 send_wont (int option)
4546
4547 /* Send IAC WONT <option> */
4548
4549 {
4550 DTF(("%s TDEBUG: send IAC WONT %02x\n", time_stamp(), option));
4551 send_telnet_option(WONT, option);
4552 }
4553
4554 /*-------------------------------------------------------------------------*/
4555 static void
4556 send_dont (int option)
4557
4558 /* Send IAC DONT <option> */
4559
4560 {
4561 DTF(("%s TDEBUG: send IAC DONT %02x\n", time_stamp(), option));
4562 send_telnet_option(DONT, option);
4563 }
4564
4565 /*-------------------------------------------------------------------------*/
4566 static void
4567 send_will (int option)
4568
4569 /* Send IAC WILL <option> */
4570
4571 {
4572 DTF(("%s TDEBUG: send IAC WILL %02x\n", time_stamp(), option));
4573 send_telnet_option(WILL, option);
4574 }
4575
4576 /*-------------------------------------------------------------------------*/
4577 static void
4578 send_do (int option)
4579
4580 /* Send IAC DO <option> */
4581
4582 {
4583 DTF(("%s TDEBUG: send IAC DO %02x\n", time_stamp(), option));
4584 send_telnet_option(DO, option);
4585 }
4586
4587 /*-------------------------------------------------------------------------*/
4588 static void
4589 reply_nil (int option UNUSED)
4590
4591 /* Dummy function which does nothing. */
4592
4593 {
4594 #ifdef __MWERKS__
4595 # pragma unused(option)
4596 #endif
4597 }
4598
4599 /*-------------------------------------------------------------------------*/
4600 static void
4601 reply_to_do_echo (int option)
4602
4603 /* Send IAC WONT <option> if we don't want noecho mode.
4604 * If we requested WILL ECHO this is the client's reply. Set NOECHO_ACK. Send
4605 * no reply. Send WILL ECHO if we want noecho but where told not to echo
4606 * (reactivate noecho mode).
4607 */
4608
4609 {
4610 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4611
4612 DTN(("reply to DO ECHO\n"));
4613 if (ip->noecho & NOECHO_MASK) {
4614 if ( !(ip->noecho & NOECHO) ) {
4615 /* We were previously told not to echo */
4616 send_will(option);
4617 }
4618 else DTN((" we don't need to say WILL\n"));
4619 /* If we already said that we will echo, be quiet */
4620 ip->noecho |= NOECHO_MASK;
4621 } else {
4622 send_wont(option);
4623 }
4624 }
4625
4626 /*-------------------------------------------------------------------------*/
4627 static void
4628 reply_to_dont_echo (int option)
4629
4630 /* If we requested WONT ECHO this is the client's reply. Do nothing.
4631 * If client requests us to not echo while we want to, send WONT ECHO and
4632 * delete NOECHO flag. The client may turn the option on again later.
4633 */
4634
4635 {
4636 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4637
4638 DTN(("reply to DONT ECHO\n"));
4639 if (ip->noecho & NOECHO_MASK) {
4640 if (!~(ip->noecho | ~NOECHO_MASK)) {
4641 /* We were granted the option before */
4642 send_wont(option);
4643 }
4644 else DTN((" we don't need to say WONT\n"));
4645 ip->noecho = (char)((ip->noecho & ~NOECHO) | NOECHO_ACK);
4646 }
4647 }
4648
4649 /*-------------------------------------------------------------------------*/
4650 static void
4651 reply_to_do_sga (int option)
4652
4653 /* Send IAC WILL <option> if Suppress Go Ahead is not already active and
4654 * mark it as active, send IAC WONT <option> if neither in NOECHO or
4655 * CHARMODE mode.
4656 */
4657
4658 {
4659 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4660
4661 DTN(("reply to DO SGA\n"));
4662 if (ip->noecho & (NOECHO_MASK|CHARMODE_MASK)) {
4663 if (!ip->supress_go_ahead) {
4664 ip->supress_go_ahead = MY_TRUE;
4665 send_will(option);
4666 }
4667 else DTN((" we don't need to say WILL\n"));
4668 } else {
4669 send_wont(option);
4670 }
4671 }
4672
4673 /*-------------------------------------------------------------------------*/
4674 static void
4675 reply_to_dont_sga (int option)
4676
4677 /* Send IAC WONT <option> if Suppress Go Ahead is active and mark it as
4678 * inactive.
4679 */
4680
4681 {
4682 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4683
4684 DTN(("reply to DONT SGA\n"));
4685 if (ip->supress_go_ahead) {
4686 ip->supress_go_ahead = 0;
4687 send_wont(option);
4688 }
4689 }
4690
4691 /*-------------------------------------------------------------------------*/
4692 static void
4693 reply_to_will_sga (int option)
4694
4695 /* Send IAC DO <option> if CHARMODE is requested but not active yet,
4696 * send IAC DONT <option> if CHARMODE is neither requested nor active.
4697 */
4698
4699 {
4700 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4701
4702 DTN(("reply to WILL SGA\n"));
4703 if (ip->noecho & CHARMODE_MASK) {
4704 if ( !(ip->noecho & CHARMODE) ) {
4705 send_do(option);
4706 }
4707 else DTN((" we don't need to say DO\n"));
4708 DTN((" noecho: %02hhx -> %02hhx\n", ip->noecho, (char)(ip->noecho | CHARMODE_MASK)));
4709 ip->noecho |= CHARMODE_MASK;
4710 } else {
4711 send_dont(option);
4712 }
4713 #ifdef SAVE_NOECHO
4714 if (ip->noecho & NOECHO_DELAYED)
4715 {
4716 DT(("'%s' set_noecho(): sending delayed WILL TELOPT_ECHO\n",
4717 get_txt(ip->ob->name)));
4718 ip->noecho &= ~NOECHO_DELAYED;
4719 if (!(ip->noecho & NOECHO_MASK))
4720 {
4721 send_will(TELOPT_ECHO);
4722 ip->noecho |= NOECHO_REQ | NOECHO;
4723 }
4724 else DT(("'%s' we don't need to say WILL\n", get_txt(ip->ob->name)));
4725 }
4726 #endif /* SAVE_NOECHO */
4727 } /* reply_to_will_sga() */
4728
4729 /*-------------------------------------------------------------------------*/
4730 static void
4731 reply_to_wont_sga (int option)
4732
4733 /* Send IAC DONT <option> if CHARMODE was granted before.
4734 */
4735
4736 {
4737 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4738
4739 DTN(("reply to WONT SGA\n"));
4740 if (ip->noecho & CHARMODE_MASK) {
4741 if (!~(ip->noecho | ~CHARMODE_MASK)) {
4742 /* We were granted the option before */
4743 send_dont(option);
4744 }
4745 else DTN((" we don't need to say DONT\n"));
4746 DTN((" noecho: %02hhx -> %02hhx\n", ip->noecho,
4747 (unsigned char)((ip->noecho & ~CHARMODE) | CHARMODE_ACK)));
4748 ip->noecho = (char)((ip->noecho & ~CHARMODE) | CHARMODE_ACK);
4749 /* Don't reset CHARMODE_REQ here: this WONT can be the answer
4750 * to the DO SGA we sent before, and the client can still answer
4751 * with DO SGA to the WILL SGA we sent as well (Windows' telnet
4752 * for example does this).
4753 * Besides, the variables are now set up to treat the input
4754 * in charmode, and changing the flag without the variables
4755 * will do Bad Things(tm).
4756 */
4757 }
4758 } /* reply_to_wont_sga() */
4759
4760 /*-------------------------------------------------------------------------*/
4761 static void
4762 mccp_telnet_neg (int option)
4763 {
4764 interactive_t *ip = O_GET_INTERACTIVE (command_giver);
4765
4766 switch (ip->tn_state)
4767 {
4768 case TS_WILL:
4769 DTF(("MCCP NEG (%d) STATE (WILL)\n", option));
4770 break;
4771 case TS_WONT:
4772 DTF(("MCCP NEG (%d) STATE (WONT)\n", option));
4773 break;
4774 case TS_DO:
4775 DTF(("MCCP NEG (%d) STATE (DO)\n", option));
4776 #ifdef USE_MCCP
4777 if (!ip->compressing)
4778 start_compress(ip, option);
4779 #endif
4780 break;
4781 case TS_DONT:
4782 DTF(("MCCP NEG (%d) STATE (DONT)\n", option));
4783 #ifdef USE_MCCP
4784 if (ip->compressing==option)
4785 end_compress(ip, MY_FALSE);
4786 #endif
4787 break;
4788 default:
4789 DTF(("MCCP NEG (%d) STATE (%hhd)\n", option, ip->tn_state));
4790 }
4791 } /* mccp_telnet_neg() */
4792
4793 /*-------------------------------------------------------------------------*/
4794 static svalue_t *
4795 h_telnet_neg (int n)
4796
4797 /* Call the H_TELNET_NEG driverhook with <n> arguments on the interpreter
4798 * stack. Return the result from that call, or NULL if the hook isn't
4799 * set. The arguments are removed from the stack in any case.
4800 */
4801
4802 {
4803 svalue_t *svp;
4804
4805 RESET_LIMITS;
4806 CLEAR_EVAL_COST;
4807 if (driver_hook[H_TELNET_NEG].type == T_STRING)
4808 {
4809 svp =
4810 secure_callback(driver_hook[H_TELNET_NEG].u.str, command_giver, n);
4811 }
4812 else if (driver_hook[H_TELNET_NEG].type == T_CLOSURE)
4813 {
4814 if (driver_hook[H_TELNET_NEG].x.closure_type == CLOSURE_LAMBDA)
4815 {
4816 free_object(driver_hook[H_TELNET_NEG].u.lambda->ob, "h_telnet_neg");
4817 driver_hook[H_TELNET_NEG].u.lambda->ob = ref_object(command_giver, "h_telnet_neg");
4818 }
4819 svp = secure_callback_lambda(&driver_hook[H_TELNET_NEG], n);
4820 }
4821 else
4822 {
4823 while (--n >= 0)
4824 pop_stack();
4825 svp = NULL;
4826 }
4827 return svp;
4828 }
4829
4830 /*-------------------------------------------------------------------------*/
4831 static void
4832 reply_h_telnet_neg (int option)
4833
4834 /* Call the H_TELNET_NEG driver hook with <tn_state> <option> as
4835 * arguments. If the hook is not defined, send WONT <option> if
4836 * the state is TS_DO, or send DONT <option> if the state is TS_WILL.
4837 */
4838
4839 {
4840 interactive_t *ip = O_GET_INTERACTIVE(command_giver);
4841 int i = 0;
4842
4843 switch(ip->tn_state) {
4844 case TS_DO:
4845 DTN(("reply to telnet_neg: DO %02x\n", option));
4846 i = DO;
4847 break;
4848 case TS_DONT:
4849 DTN(("reply to telnet_neg: DONT %02x\n", option));
4850 i = DONT;
4851 break;
4852 case TS_WILL:
4853 DTN(("reply to telnet_neg: WILL %02x\n", option));
4854 i = WILL;
4855 break;
4856 case TS_WONT:
4857 DTN(("reply to telnet_neg: WONT %02x\n", option));
4858 i = WONT;
4859 break;
4860 default:
4861 debug_message("%s Invalid tn_state %hhd for interactive '%s'\n"
4862 , time_stamp(), ip->tn_state, get_txt(ip->ob->name));
4863 break;
4864 }
4865 push_number(inter_sp, i);
4866 push_number(inter_sp, option);
4867 if (!h_telnet_neg(2)) {
4868 DTN((" using default methods\n"));
4869 switch(ip->tn_state) {
4870 case TS_DO:
4871 DTN((" -> WONT %02x\n", option));
4872 send_wont(option);
4873 break;
4874 case TS_WILL:
4875 DTN((" -> DONT %02x\n", option));
4876 send_dont(option);
4877 break;
4878 }
4879 }
4880 } /* reply_h_telnet_neg() */
4881
4882 /*-------------------------------------------------------------------------*/
4883 void
4884 init_telopts (void)
4885
4886 /* Initialise the telopts_xxx[] tables.
4887 * The default setting is such that requests are ignored or rejected.
4888 */
4889
4890 {
4891 int i;
4892
4893 /* Pass all telnet options that we're not
4894 * able to handle to the mudlib.
4895 */
4896 for (i = NTELOPTS; --i >= 0; ) {
4897 telopts_do[i] = reply_h_telnet_neg;
4898 telopts_dont[i] = reply_h_telnet_neg;
4899 telopts_will[i] = reply_h_telnet_neg;
4900 telopts_wont[i] = reply_h_telnet_neg;
4901 }
4902
4903 telopts_do[TELOPT_ECHO] = reply_to_do_echo;
4904 telopts_dont[TELOPT_ECHO] = reply_to_dont_echo;
4905
4906 /* Go Ahead does not make any sense when coupling multiple
4907 * interactive users. It is debatable if we are sending
4908 * Go Ahead every time it is appropriate (i.e. , never),
4909 * or we supress it all the time.
4910 * Unfortunately, SGA is also often associated with
4911 * character-at-a-time mode - the RFC even mandates this
4912 * double meaning - which we certainly don't want.
4913 * It might cause problems when we reject Supress Go Ahead
4914 * when some stupid client thinks that the ECHO option need
4915 * be coupled with SGA .
4916 * Thus, reject SGA in general, but not while
4917 * ip->noecho & NOECHO_MASK is true.
4918 */
4919 telopts_do[TELOPT_SGA] = reply_to_do_sga;
4920 telopts_dont[TELOPT_SGA] = reply_to_dont_sga;
4921 telopts_will[TELOPT_SGA] = reply_to_will_sga;
4922 telopts_wont[TELOPT_SGA] = reply_to_wont_sga;
4923
4924 /* Mud specific protocols */
4925 telopts_do[TELOPT_COMPRESS] = mccp_telnet_neg;
4926 telopts_dont[TELOPT_COMPRESS] = mccp_telnet_neg;
4927 telopts_will[TELOPT_COMPRESS] = mccp_telnet_neg;
4928 telopts_wont[TELOPT_COMPRESS] = mccp_telnet_neg;
4929
4930 telopts_do[TELOPT_COMPRESS2] = mccp_telnet_neg;
4931 telopts_dont[TELOPT_COMPRESS2] = mccp_telnet_neg;
4932 telopts_will[TELOPT_COMPRESS2] = mccp_telnet_neg;
4933 telopts_wont[TELOPT_COMPRESS2] = mccp_telnet_neg;
4934 } /* init_telopts() */
4935
4936 /*-------------------------------------------------------------------------*/
4937 void
4938 mudlib_telopts (void)
4939
4940 /* Set all telopts_xxx[] entries to reply_h_telnet_neg().
4941 * This means that the mudlib does all the telnet negotiation.
4942 * It is called whenever driver hook H_NOECHO is set.
4943 */
4944
4945 {
4946 int i;
4947
4948 DT(("All telnet options set to the mudlib.\n"));
4949 for (i = NTELOPTS; --i >= 0; ) {
4950 telopts_do[i] = telopts_dont[i] =
4951 telopts_will[i] = telopts_wont[i] = reply_h_telnet_neg;
4952 }
4953 } /* mudlib_telopts() */
4954
4955 /*-------------------------------------------------------------------------*/
4956 static INLINE Bool
4957 is_charmode (interactive_t * ip)
4958
4959 /* Return TRUE if <ip> has charmode enabled, and FALSE if not.
4960 */
4961
4962 {
4963 return (ip->noecho & CHARMODE_REQ)
4964 && ( ip->text[0] != input_escape
4965 || find_no_bang(ip) & IGNORE_BANG
4966 )
4967
4968 ;
4969 } /* is_charmode() */
4970
4971 /*-------------------------------------------------------------------------*/
4972 static void
4973 telnet_neg (interactive_t *ip)
4974
4975 /* Process the data read from the socket, performing any telnet negotiations
4976 * necessary, and extract the 'pure' command text. When the function returns,
4977 * all new data in .text[] has been used and .text_end set back as far
4978 * as possible.
4979 *
4980 * The start state for the telnet machine is TS_DATA, and whenever a command
4981 * text has been completed, it assumes the TS_READY state.
4982 *
4983 * The function tn_end and goes on until it reaches text_end or a full newline.
4984 *
4985 * When it returns:
4986 * tn_end is set to the first unprocessed character.
4987 * When a full newline is found:
4988 * Processed commands start at command_start and are \0 terminated strings
4989 * state is set to READY
4990 * else
4991 * Processed commands start at command_start and end at command_end-1
4992 * state is set to DATA (or something else if we got a fragmented
4993 * telnet negotiation).
4994 *
4995 * text_end could move a bit to the start of text if we deleted chars
4996 * from the raw input string (e.g. because it was an IAC).
4997 *
4998 * If gobble_char is set, that char is removed from a fresh text packet.
4999 * Removing of unwanted chars inside of a packet is done at the appropriate
5000 * place (case '\r':). There is no gobbling of <LN><CR> sequences in
5001 * character mode (why not?). Code would have to be added at case '\n':
5002 * to gobble them in-packet.
5003 *
5004 * Example:
5005 * text = "say hello\r\nsay hi\r\n";
5006 *
5007 * Output would be:
5008 * text = "say hello\0\nsay hi\r\n";
5009 *
5010 * command_start = 0
5011 * command_end = 0
5012 * tn_end = 11 (s of 2nd say)
5013 * text_end stays at 19 (first unused char in text)
5014 * state = TS_READY
5015 *
5016 * After a second call of telnet_neg (almost always done by get_message())
5017 * will pre process the second command:
5018 *
5019 * text = "say hi\0lo\0\nsay hi\r\n";
5020 *
5021 * command_start = 0
5022 * command_end = 0
5023 * tn_end = 7
5024 * text_end = 7
5025 * state = READY
5026 */
5027
5028 {
5029 fd_set exceptfds;
5030 char *from; /* Next char to process */
5031 char *to; /* Where to store the extracted command text */
5032 int state;
5033 int ch; /* Current character */
5034 char *first; /* Begin of the last pure command text */
5035 char *end; /* End of data in text[] */
5036
5037 first = ip->text;
5038 from = &first[ip->tn_end];
5039 end = &first[ip->text_end];
5040
5041 DTN(("telnet_neg: state %hhd\n", ip->tn_state));
5042
5043 /* Gobble the character *from if gobble_char is set.
5044 * Also test for the end of current buffer content.
5045 *
5046 * If we want to gobble NL, we also gobble NUL
5047 * (used for CR NL and CR NUL digraphs)
5048 */
5049 for (;;)
5050 {
5051 if (from >= end) {
5052 #if 0 /* cannot happen with the current calling pattern */
5053 if (ip->state == TS_READY) return;
5054 #endif
5055 ip->text_end = ip->tn_end = ip->command_end;
5056 return;
5057 }
5058 if (ip->gobble_char) {
5059 DTN(("t_n: gobble char %02hhx (in buf: %02x)\n"
5060 , ip->gobble_char, *from));
5061 if (*from == ip->gobble_char
5062 || (*from == '\0' && ip->gobble_char == '\n')
5063 )
5064 {
5065 from++;
5066 }
5067 ip->gobble_char = '\0';
5068 continue;
5069 }
5070 break;
5071 }
5072 to = &first[ip->command_end];
5073
5074 /* The processing loop */
5075
5076 do {
5077 ch = (*from++ & 0xff);
5078 DTN(("t_n: processing %02hhx '%c'\n"
5079 , (unsigned char)ch, ch));
5080 switch(ip->tn_state)
5081 {
5082 case TS_READY:
5083 DTN(("t_n: still in TS_READY - return\n"));
5084 /* Previous command hasn't been read yet - don't clobber it! */
5085 return;
5086
5087 ts_data:
5088 /* Most state functions end with a jump here to check if they
5089 * exhausted their input.
5090 */
5091 if (from >= end)
5092 {
5093 ip->text_end = ip->tn_end = ip->command_end = (short)(to - first);
5094 DTN(("t_n: (ts_data) from >= end by %td, text_end := %hd\n (max %d)"
5095 , (ptrdiff_t)(from-end), ip->text_end, MAX_TEXT));
5096 *to = '\0';
5097 if (ip->text_end >= MAX_TEXT)
5098 {
5099 /* this looks like a super-long command.
5100 * Return the text so far as partial command and restart
5101 * input from the beginning.
5102 * In charmode, we must not reset command_end, otherwise
5103 * it might fall under command_start.
5104 */
5105 ip->tn_state = TS_READY;
5106 ip->tn_end = 0;
5107 ip->text_end = 0;
5108 if (!(ip->noecho & (CHARMODE_REQ|CHARMODE)))
5109 {
5110 ip->command_end = 0;
5111 }
5112 return;
5113 }
5114 return;
5115 }
5116 ch = (*from++ & 0xff);
5117 DTN(("t_n: (ts_data) processing %02hhx '%c'\n"
5118 , (unsigned char)ch, ch));
5119 /* FALLTHROUGH */
5120
5121 case TS_DATA: /* --- Copy/interpret plain data --- */
5122 switch(ch)
5123 {
5124 case IAC:
5125 new_iac:
5126 if (ip->tn_enabled)
5127 {
5128 state = TS_IAC;
5129 change_state:
5130 DTN(("t_n: new state %d\n", state));
5131 ip->tn_state = (char)state;
5132 continue;
5133 }
5134 /* FALLTHROUGH if !tn_enabled */
5135
5136 case '\b': /* Backspace */
5137 case 0x7f: /* Delete */
5138 /* In Linemode, just move to one char back.
5139 * In Charmode with escaped input, write the data gathered
5140 * so far and add a rubout sequence ('\b \b').
5141 * In Charmode with unescaped input, just pass it on to
5142 * the mudlib.
5143 *
5144 * If telnet is disabled, fallthrough to the general
5145 * data handling.
5146 */
5147 if (ip->tn_enabled)
5148 {
5149 if ( !(ip->noecho & CHARMODE_REQ) )
5150 {
5151 if (to > first)
5152 to--;
5153 goto ts_data;
5154 }
5155
5156 if (ip->text[0] == input_escape
5157 && ! (find_no_bang(ip) & IGNORE_BANG) )
5158 {
5159 if (to > &ip->text[ip->chars_ready])
5160 {
5161 comm_socket_write(&ip->text[ip->chars_ready]
5162 , (size_t)(to - &ip->text[ip->chars_ready])
5163 , ip, 0);
5164 ip->chars_ready = to - ip->text;
5165 }
5166 if (to > first)
5167 {
5168 comm_socket_write("\b \b", 3, ip, 0);
5169 to--;
5170 ip->chars_ready--;
5171 }
5172 goto ts_data;
5173 }
5174 } /* if (ip->tn_enabled) */
5175 /* FALLTHROUGH */
5176
5177 default:
5178 *to++ = (char)ch;
5179 /* FALLTHROUGH */
5180
5181 case '\0':
5182 /* In Charmode, we should return the \0 (as with CR and LF),
5183 * but for the caller the \0 has magical properties.
5184 */
5185 goto ts_data;
5186
5187 case '\r':
5188 /* In Charmode we have to return the \r.
5189 */
5190 if (is_charmode(ip))
5191 {
5192 *to++ = (char)ch;
5193 goto ts_data;
5194 }
5195
5196 if (from >= end)
5197 {
5198 /* This might be a fragmented CR NL, CR NUL, or
5199 * a broken client that ends lines with CR only.
5200 * We proceed as full newline now, but gobble
5201 * NL or NUL if they are sent afterwards.
5202 */
5203 ip->gobble_char = '\n';
5204 }
5205 else
5206 {
5207 ch = (*from++ & 0xff);
5208 /* gobble following NL and NUL */
5209 if (ch && ch != '\n')
5210 from--;
5211 }
5212
5213 full_newline:
5214 /* Proper line end found: set telnet machine into TS_READY,
5215 * terminate the command with \0 and return.
5216 */
5217 {
5218 ip->tn_state = TS_READY;
5219 ip->command_end = 0;
5220 ip->tn_end = (short)(from - first);
5221
5222 /* Even in charmode we append the NUL in case the client
5223 * refused to use charmode, because then get_message()
5224 * will treat the data as if in linemode and expect
5225 * a trailing NUL.
5226 */
5227 *to = '\0';
5228 return;
5229 }
5230
5231 case '\n':
5232 /* In Charmode we have to return the \n.
5233 */
5234 if (is_charmode(ip))
5235 {
5236 *to++ = (char)ch;
5237 goto ts_data;
5238 }
5239
5240 ip->gobble_char = '\r';
5241 goto full_newline;
5242 } /* switch(ch) */
5243
5244 /* NOTREACHED */
5245
5246 ts_iac:
5247 case TS_IAC:
5248 DTN(("t_n: state IAC\n"));
5249 /* Begin a telnet negotiation */
5250 switch(ch)
5251 {
5252 case IAC:
5253 DTN(("t_n: got IAC\n"));
5254 *to++ = ch;
5255 ip->tn_state = state = TS_DATA;
5256 goto ts_data;
5257 case WILL:
5258 DTN(("t_n: got WILL\n"));
5259 state = TS_WILL;
5260 goto change_state;
5261 case WONT:
5262 DTN(("t_n: got WONT\n"));
5263 state = TS_WONT;
5264 goto change_state;
5265 case DO:
5266 DTN(("t_n: got DO\n"));
5267 state = TS_DO;
5268 goto change_state;
5269 case DONT:
5270 DTN(("t_n: got DONT\n"));
5271 state = TS_DONT;
5272 goto change_state;
5273 case SB:
5274 DTN(("t_n: got SB\n"));
5275 ip->tn_start = (short)(to - first);
5276 state = TS_SB;
5277 goto change_state;
5278 case DM:
5279 DTN(("t_n: got DM\n"));
5280 data_mark:
5281 if (ip->ts_data == TS_SYNCH)
5282 {
5283 struct timeval timeout;
5284
5285 FD_ZERO(&exceptfds);
5286 FD_SET(ip->socket, &exceptfds);
5287 timeout.tv_sec = 0;
5288 timeout.tv_usec = 0;
5289 if (! socket_select(ip->socket + 1, 0, 0, &exceptfds,
5290 &timeout))
5291 {
5292 if (d_flag)
5293 debug_message("%s Synch operation finished.\n"
5294 , time_stamp());
5295 ip->ts_data = TS_DATA;
5296 }
5297 }
5298 break;
5299 case NOP:
5300 DTN(("t_n: got NOP\n")); break;
5301 case GA:
5302 DTN(("t_n: got GA\n")); break;
5303 default:
5304 DTN(("t_n: got %02hhx\n", ch)); break;
5305 break;
5306 } /* switch(ch) */
5307 state = ip->ts_data;
5308 goto change_state;
5309
5310 case TS_WILL:
5311 command_giver = ip->ob;
5312 if (ch < NTELOPTS) {
5313 DTN(("t_n: state WILL got %s (%02hhx)\n"
5314 , telopts[ch], ch));
5315 if (d_flag)
5316 debug_message("%s Will %s\n", time_stamp(), telopts[ch]);
5317 (*telopts_will[ch])(ch);
5318 } else {
5319 debug_message("%s Unknown telnet option Will %hhd\n"
5320 , time_stamp(), ch);
5321 send_dont(ch);
5322 }
5323 state = ip->ts_data;
5324 goto change_state;
5325
5326 case TS_WONT:
5327 command_giver = ip->ob;
5328 if (ch < NTELOPTS) {
5329 DTN(("t_n: state WONT got %s (%02hhx)\n"
5330 , telopts[ch], ch));
5331 if (d_flag)
5332 debug_message("%s Wont %s\n", time_stamp(), telopts[ch]);
5333 (*telopts_wont[ch])(ch);
5334 } else {
5335 debug_message("%s Unknown telnet option Wont %hhd\n"
5336 , time_stamp(), ch);
5337 }
5338 state = ip->ts_data;
5339 goto change_state;
5340
5341 case TS_DO:
5342 command_giver = ip->ob;
5343 if (ch < NTELOPTS) {
5344 DTN(("t_n: state DO got %s (%02hhx)\n"
5345 , telopts[ch], ch));
5346 if (d_flag)
5347 debug_message("%s Do %s\n", time_stamp(), telopts[ch]);
5348 (*telopts_do[ch])(ch);
5349 } else {
5350 debug_message("%s Unknown telnet option Do %hhd\n"
5351 , time_stamp(), ch);
5352 send_wont(ch);
5353 }
5354 state = ip->ts_data;
5355 goto change_state;
5356
5357 case TS_DONT:
5358 command_giver = ip->ob;
5359 if (ch < NTELOPTS) {
5360 DTN(("t_n: state DONT got %s (%02hhx)\n"
5361 , telopts[ch], ch));
5362 if (d_flag)
5363 debug_message("%s Dont %s\n", time_stamp(), telopts[ch]);
5364 (*telopts_dont[ch])(ch);
5365 } else {
5366 debug_message("%s Unknown telnet option Dont %hhd\n"
5367 , time_stamp(), ch);
5368 }
5369 state = ip->ts_data;
5370 goto change_state;
5371
5372 case TS_SB:
5373 DTN(("t_n: state TS_SB got %02hhx\n", ch));
5374 if (ch == IAC) {
5375 state = TS_SB_IAC;
5376 goto change_state;
5377 }
5378 *to++ = (char)ch;
5379 continue;
5380
5381 case TS_SB_IAC:
5382 {
5383 mp_int size;
5384 vector_t *v;
5385
5386 DTN(("t_n: state TS_SB_IAC got %02hhx\n", ch));
5387 if (ch == IAC) {
5388 DTN(("t_n: that is: state TS_SB_IAC got IAC\n"));
5389 *to++ = (char)ch;
5390 state = TS_SB;
5391 goto change_state;
5392 } else if ((ch == SE || ch == SB)
5393 && ( (size = (to - first) - ip->tn_start - 1) <= (mp_int)max_array_size
5394 || !max_array_size)
5395 && size >= 0
5396 && (current_object = ip->ob, v = allocate_array(size)) )
5397 {
5398 unsigned char *str;
5399 svalue_t *svp;
5400
5401 str = (unsigned char *)&ip->text[ip->tn_start];
5402 DTN(("t_n: that is: state TS_SB_IAC got useful SE or SB: neg SB %02hhx (%"PRIdMPINT" bytes)\n", *str, size));
5403 push_number(inter_sp, SB);
5404 push_number(inter_sp, *str++);
5405 svp = v->item;
5406 while (--size >= 0) {
5407 svp->u.number = *str++;
5408 svp++;
5409 }
5410 push_array(inter_sp, v);
5411 command_giver = ip->ob;
5412 h_telnet_neg(3);
5413 }
5414 to = &first[ip->tn_start];
5415 if (ch != SE)
5416 goto ts_iac;
5417 state = ip->ts_data;
5418 goto change_state;
5419 }
5420
5421 case TS_SYNCH:
5422 DTN(("t_n: state TS_SYNCH got %02hhx\n", ch));
5423 if (ch == IAC) goto new_iac;
5424 if (ch == DM) goto data_mark;
5425 continue;
5426
5427 default:
5428 if (d_flag)
5429 debug_message("%s Bad state: 0x%hhx\n", time_stamp(), ip->tn_state);
5430 state = TS_DATA;
5431 goto change_state;
5432 } /* switch (ip->tn_state) */
5433
5434 } while(from < end);
5435
5436 /* We used all the new data in .text[] but found no complete command.
5437 * Reset all pointers necessary to read new data.
5438 */
5439
5440 ip->text_end = ip->tn_end = ip->command_end = (short)(to - first);
5441 if (ip->text_end == MAX_TEXT)
5442 {
5443 /* telnet negotiation shouldn't have such large data chunks.
5444 * Ignore all data altogether and return to text mode.
5445 */
5446 ip->text_end = ip->tn_end = ip->command_end = 0;
5447 ip->tn_start = ip->command_start = 0;
5448 ip->tn_state = TS_DATA;
5449 }
5450 } /* telnet_neg() */
5451
5452 /* End of Telnet support */
5453 /*=========================================================================*/
5454 /* ERQ Support
5455 */
5456
5457 #ifdef ERQ_DEMON
5458 /*-------------------------------------------------------------------------*/
5459 void
5460 start_erq_demon (const char *suffix, size_t suffixlen)
5461
5462 /* Start the ERQ demon from the path 'ERQFILE<suffix>' and setup
5463 * the pending_erq[] array.
5464 */
5465
5466 {
5467 erq_callback_t *erqp;
5468 char path[MAXPATHLEN+1];
5469 int sockets[2];
5470 int pid, i;
5471 char c;
5472
5473 /* Create the freelist in pending_erq[] */
5474 pending_erq[0].fun.type = T_INVALID;
5475 pending_erq[0].fun.u.generic = NULL;
5476
5477 erqp = pending_erq + 1;
5478 while (erqp < &pending_erq[MAX_PENDING_ERQ])
5479 {
5480 erqp->fun.u.generic = (void *)(erqp - 1);
5481 erqp->fun.type = T_INVALID;
5482 erqp++;
5483 }
5484 free_erq = &pending_erq[MAX_PENDING_ERQ-1];
5485
5486 /* Create the sockets to talk to the ERQ */
5487 /* TODO: Add tests to configure if the system really implements AF_UNIX or socketpair() */
5488 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
5489 {
5490 perror("socketpair");
5491 return;
5492 }
5493
5494 (void)signal(SIGCLD, SIG_IGN); /* don't create zombie processes */
5495
5496 printf("%s Attempting to start erq '%s%s'.\n"
5497 , time_stamp(), erq_file, suffix);
5498 debug_message("%s Attempting to start erq '%s%s'.\n"
5499 , time_stamp(), erq_file, suffix);
5500
5501 /* Close inherited sockets first. */
5502 for (i = 0; i < numports; i++)
5503 if (port_numbers[i] < 0)
5504 set_close_on_exec(-port_numbers[i]);
5505
5506 if ((pid = fork()) == 0)
5507 {
5508 /* Child */
5509 dup2(sockets[0], 0);
5510 dup2(sockets[0], 1);
5511 close(sockets[0]);
5512 close(sockets[1]);
5513
5514 if (strlen(erq_file) + 1 + suffixlen <= sizeof path)
5515 {
5516 sprintf(path, "%s%.*s", erq_file, (int)suffixlen, suffix);
5517 if (erq_args)
5518 execv((char *)path, erq_args);
5519 else
5520 execl((char *)path, "erq", "--forked", (char*)0);
5521 }
5522 write(1, "0", 1); /* indicate failure back to the driver */
5523 _exit(1);
5524 }
5525
5526 close(sockets[0]);
5527 if (pid == -1) {
5528 close(sockets[1]);
5529 return;
5530 }
5531
5532 /* Read the first character from the ERQ. If it's '0', the ERQ
5533 * didn't start.
5534 */
5535 read(sockets[1], &c, 1);
5536 if (c == '0') {
5537 close(sockets[1]);
5538
5539 printf("%s Failed to start erq.\n", time_stamp());
5540 debug_message("%s Failed to start erq.\n", time_stamp());
5541 return;
5542 }
5543
5544 /* ERQ is up and running */
5545 erq_demon = sockets[1];
5546 set_socket_nonblocking(erq_demon);
5547 if (socket_number(erq_demon) >= min_nfds)
5548 min_nfds = socket_number(erq_demon)+1;
5549 } /* start_erq_demon() */
5550
5551 /*-------------------------------------------------------------------------*/
5552 static void
5553 shutdown_erq_demon (void)
5554
5555 /* Close the connection to the ERQ.
5556 * This method is to be used directly only on game shutdown, otherwise
5557 * use stop_erq_demon() instead.
5558 */
5559
5560 {
5561 if (erq_demon < 0)
5562 return;
5563
5564 socket_close(erq_demon);
5565 erq_demon = FLAG_NO_ERQ;
5566 erq_pending_len = 0;
5567 input_from_erq = &buf_from_erq[0];
5568 } /* shutdown_erq_demon() */
5569
5570 /*-------------------------------------------------------------------------*/
5571 static void
5572 stop_erq_demon (Bool notify)
5573
5574 /* Close the connection to the ERQ and inform all pending requests
5575 * about this. If <notify> is set, the hook H_ERQ_STOP is called.
5576 */
5577
5578 {
5579 erq_callback_t *erqp;
5580 int i;
5581
5582 if (erq_demon < 0)
5583 return;
5584
5585 shutdown_erq_demon();
5586
5587 /* Inform all pending requests about the loss.
5588 */
5589 erqp = pending_erq;
5590 i = MAX_PENDING_ERQ;
5591 do {
5592 if (erqp->fun.type == T_CLOSURE)
5593 {
5594 *++inter_sp = erqp->fun;
5595 erqp->fun.type = T_INVALID;
5596 erqp->fun.u.generic = (void *)free_erq;
5597 free_erq = erqp;
5598 CLEAR_EVAL_COST;
5599 RESET_LIMITS;
5600 callback_master(STR_STALE_ERQ, 1);
5601 }
5602 erqp++;
5603 } while (--i);
5604
5605 /* If desired, call H_ERQ_STOP to notify the situation.
5606 */
5607 if (notify)
5608 {
5609 RESET_LIMITS;
5610 CLEAR_EVAL_COST;
5611 if (driver_hook[H_ERQ_STOP].type == T_CLOSURE) {
5612 secure_callback_lambda(&driver_hook[H_ERQ_STOP], 0);
5613 }
5614 }
5615 } /* stop_erq_demon() */
5616
5617 /*-------------------------------------------------------------------------*/
5618 svalue_t *
5619 f_attach_erq_demon (svalue_t *sp)
5620
5621 /* EFUN: attach_erq_demon()
5622 *
5623 * int attach_erq_demon(object ob, int do_close)
5624 * int attach_erq_demon(string name, int do_close)
5625 *
5626 * In the first form, take away the connection from <ob> and store it as
5627 * _the_ erq connection. <ob> thus becomes a normal non-interactive object.
5628 * In the second form, try to start the ERQ demon from the path
5629 * 'ERQFILE<name>' (ERQFILE defaults to BINDIR/erq). <name> must not
5630 * contain '/..' sequences.
5631 *
5632 * If there is already an ERQ demon connected to the driver, the function
5633 * will fail unless <do_close> is set to 1 or any other odd integer; in
5634 * this case the connection to the old ERQ will be closed first.
5635 *
5636 * Return svalue.number 1 on success, 0 else.
5637 */
5638
5639 {
5640 object_t *ob;
5641 interactive_t *ip;
5642 string_t *suffix;
5643
5644 /* Test for the first form: (object ob, int do_close) */
5645 if (sp[-1].type == T_OBJECT)
5646 {
5647 ob = sp[-1].u.ob;
5648 if (!O_SET_INTERACTIVE(ip, ob))
5649 {
5650 errorf("Bad arg 1 to attach_erq_demon(): object is not interactive.\n");
5651 /* NOTREACHED */
5652 return sp;
5653 }
5654
5655 sp--;
5656 deref_object(ob, "attach_erq_demon");
5657 put_number(sp, 0);
5658 /* we need to read sp[1] below, thus don't overwrite it now. */
5659 if (privilege_violation4(STR_ATTACH_ERQ_DEMON,
5660 ob, 0, sp[1].u.number, sp+1))
5661 {
5662 if (erq_demon != FLAG_NO_ERQ) {
5663 if (sp[1].u.number & 1) {
5664 stop_erq_demon(0);
5665 erq_demon = FLAG_ERQ_STOP;
5666 } else {
5667 return sp;
5668 }
5669 }
5670 erq_proto_demon = ip->socket;
5671 ip->do_close = FLAG_PROTO_ERQ;
5672 sp->u.number = 1;
5673 }
5674 return sp;
5675 }
5676
5677 /* Otherwise the argument is a string */
5678
5679 suffix = sp[-1].u.str;
5680 if (mstrstr(suffix, "/.."))
5681 {
5682 errorf("Bad arg 1 to attach_erq_demon(): illegal path.\n");
5683 /* NOTREACHED */
5684 return sp;
5685 }
5686
5687 {
5688 int n;
5689
5690 sp--;
5691 n = 0;
5692 if (privilege_violation4(STR_ATTACH_ERQ_DEMON,
5693 0, suffix, sp[1].u.number, sp+1))
5694 {
5695 if (erq_demon != FLAG_NO_ERQ)
5696 {
5697 if (sp[1].u.number & 1) {
5698 stop_erq_demon(0);
5699 } else {
5700 goto return_result;
5701 }
5702 erq_proto_demon = -1;
5703 }
5704 start_erq_demon(get_txt(suffix), mstrsize(suffix));
5705 n = 1;
5706 }
5707 return_result:
5708 free_svalue(sp);
5709 put_number(sp, n);
5710 return sp;
5711 }
5712
5713 /* NOTREACHED */
5714 return NULL;
5715 } /* f_attach_erq_demon() */
5716
5717 /*-------------------------------------------------------------------------*/
5718 static Bool
5719 send_erq (int handle, int request, const char *arg, size_t arglen)
5720
5721 /* Send compose an ERQ message out of <handle>, <request> and <arg>
5722 * and send it to the ERQ. If all the data can't be sent now, the
5723 * next call to send_erq() will send the rest.
5724 *
5725 * Return FALSE if the data couldn't be sent, TRUE on success.
5726 *
5727 * SOCK_SEQPACKET is not portable enough, thus make special provisions
5728 * to deliver messages in an atomic fashion.
5729 */
5730
5731 {
5732 static char buf[ERQ_MAX_SEND], *pending;
5733 long wrote;
5734
5735 if (erq_demon < 0)
5736 return MY_FALSE;
5737
5738 /* Try to send the pending data */
5739 if (erq_pending_len)
5740 {
5741 wrote = socket_write(erq_demon, pending, erq_pending_len);
5742 if (wrote > 0) {
5743 pending += wrote;
5744 erq_pending_len -= wrote;
5745 }
5746 if (erq_pending_len)
5747 return MY_FALSE;
5748 }
5749
5750 if (arglen + 9 > sizeof buf)
5751 return MY_FALSE;
5752
5753 /* Create the message and add it to buf[] */
5754 erq_pending_len = arglen + 9;
5755 *(uint32*)buf = htonl(erq_pending_len);
5756 *(uint32*)(buf+4) = htonl(handle);
5757 buf[8] = (char)request;
5758 memcpy(buf + 9, arg, arglen);
5759
5760 /* Send as much of buf[] as possible */
5761 pending = buf;
5762 wrote = socket_write(erq_demon, buf, erq_pending_len);
5763 if (wrote > 0) {
5764 pending += wrote;
5765 erq_pending_len -= wrote;
5766 }
5767
5768 return MY_TRUE;
5769 } /* send_erq() */
5770
5771 /*-------------------------------------------------------------------------*/
5772 svalue_t *
5773 f_send_erq (svalue_t *sp)
5774
5775 /* EFUN: send_erq()
5776 *
5777 * int send_erq(int request, string|int* data, closure callback)
5778 *
5779 * Send a request of type <request> and the data <data> to the ERQ>
5780 * If <callback> is set to a closure, it will be called with the
5781 * response from the ERQ.
5782 *
5783 * The function returns svalue.number 1 on success, and 0 on failure.
5784 *
5785 * The function causes a privilege violation "erq".
5786 */
5787
5788 {
5789 char *arg;
5790 size_t arglen;
5791 erq_callback_t *new_erq;
5792 int i;
5793 p_int erq_request;
5794
5795 /* Set arg with the data to send. */
5796
5797 if (sp[-1].type == T_STRING) {
5798 arg = get_txt(sp[-1].u.str);
5799 arglen = mstrsize(sp[-1].u.str);
5800 }
5801 else /* it's a pointer */
5802 {
5803 vector_t *v;
5804 svalue_t *svp;
5805 char *cp;
5806 p_int j;
5807
5808 v = sp[-1].u.vec;
5809 arglen = VEC_SIZE(v);
5810 cp = arg = xalloc(arglen);
5811 if (!arg) {
5812 errorf("Out of memory (%zu bytes) in send_erq() for allocating "
5813 "temporary buffer.\n", arglen);
5814 }
5815 svp = &v->item[0];
5816 for (j = (p_int)arglen; --j >= 0; )
5817 *cp++ = (char)(*svp++).u.number;
5818 }
5819
5820 erq_request = sp[-2].u.number;
5821
5822 /* Test if this call is allowed. */
5823
5824 if (!privilege_violation4(STR_SEND_ERQ, 0, STR_EMPTY
5825 , erq_request & (~ERQ_CB_STRING)
5826 , sp))
5827 {
5828 goto failure;
5829 }
5830
5831 /* Store the callback closure. If none is given, use the
5832 * default callback.
5833 */
5834
5835 new_erq = NULL;
5836
5837 if (sp->type == T_NUMBER) { /* it's the number 0 */
5838 new_erq = &pending_erq[MAX_PENDING_ERQ];
5839 new_erq->fun.u.generic = (void *)free_erq;
5840 }
5841 else if (sp->type == T_CLOSURE
5842 && sp->x.closure_type != CLOSURE_UNBOUND_LAMBDA)
5843 {
5844 new_erq = free_erq;
5845 }
5846
5847 /* Send the request and make up the result. */
5848
5849 if (new_erq
5850 && 0 != (i = send_erq(new_erq - pending_erq, erq_request & (~ERQ_CB_STRING)
5851 , arg, arglen))
5852 )
5853 {
5854 free_erq = (erq_callback_t *)new_erq->fun.u.generic;
5855 new_erq->fun = *sp;
5856 new_erq->string_arg = (erq_request & ERQ_CB_STRING) != 0;
5857 }
5858 else
5859 {
5860 failure:
5861 i = 0;
5862 free_svalue(sp);
5863 }
5864 /* cleanup */
5865 if (sp[-1].type != T_STRING) {
5866 /* free arg only if sp-1 is not a string */
5867 xfree(arg);
5868 }
5869 free_svalue(--sp);
5870 (*--sp).u.number = i;
5871
5872 return sp;
5873 } /* f_send_erq() */
5874
5875 /*-------------------------------------------------------------------------*/
5876 static long
5877 read_32 (char *str)
5878
5879 /* Read a 32 bit value from a possibly unaligned network byte order
5880 * representation.
5881 */
5882
5883 {
5884 unsigned char *p = (unsigned char *)str;
5885
5886 return (long)p[0]<<24 | (long)p[1]<<16 | (long)p[2]<<8 | p[3];
5887 }
5888
5889 /*-------------------------------------------------------------------------*/
5890 static void
5891 add_ip_entry (struct in_addr addr, const char *name)
5892
5893 /* Add a new IP address <addr>/hostname <name> pair to the cache iptable[].
5894 * If the <addr> already exists in the table, replace the old tabled name
5895 * with the new one.
5896 */
5897
5898 {
5899 int i, ix;
5900 Bool new_entry;
5901
5902 ix = -1;
5903 new_entry = MY_FALSE;
5904 for (i = 0; i < IPSIZE; i++)
5905 {
5906 if (!memcmp(&(iptable[i].addr.s_addr), &addr.s_addr, sizeof(iptable[i].addr.s_addr)))
5907 {
5908 ix = i;
5909 break;
5910 }
5911 }
5912
5913 if (ix < 0)
5914 {
5915 ix = ipcur;
5916 new_entry = MY_TRUE;
5917 }
5918
5919 iptable[ix].addr = addr;
5920 if (iptable[ix].name)
5921 free_mstring(iptable[ix].name);
5922 iptable[ix].name = new_tabled(name);
5923
5924 if (new_entry)
5925 ipcur = (ipcur+1) % IPSIZE;
5926 } /* add_ip_entry() */
5927
5928 /*-------------------------------------------------------------------------*/
5929 #ifdef USE_IPV6
5930
5931 static void
5932 update_ip_entry (const char *oldname, const char *newname)
5933
5934 /* Change the IP name <oldname> in the iptable[] to <newname>.
5935 * If the <oldname> is not in the table, nothing happens.
5936 */
5937
5938 {
5939 int i, ix;
5940 Bool new_entry;
5941
5942 ix = -1;
5943 new_entry = MY_FALSE;
5944 for (i = 0; i < IPSIZE; i++)
5945 {
5946 if (iptable[i].name
5947 && !strncmp(get_txt(iptable[i].name), oldname, mstrsize(iptable[i].name))
5948 )
5949 {
5950 free_mstring(iptable[i].name);
5951 iptable[i].name = new_tabled(newname);
5952 }
5953 }
5954 } /* update_ip_entry() */
5955
5956 /*-------------------------------------------------------------------------*/
5957 static int
5958 open_ipv6_conn( const char *hostname, const unsigned short int port
5959 , struct sockaddr_in * pTarget)
5960
5961 /* Create a non-blocking IPv6/IPv4 tcp connnection to the given
5962 * <hostname>:<port>. The <hostname> is first interpreted as IPv6
5963 * address, and if that fails, as IPv4 address.
5964 *
5965 * Result is the socket (with the connnection possibly still in process
5966 * of being opened), or -1 on a failure.
5967 *
5968 * The completed sockaddr_in is passed back in *<pTarget> as well.
5969 *
5970 * WARNING: Not threadsafe!
5971 */
5972
5973 {
5974 int sock;
5975 int con = 0;
5976 int fd_flags;
5977
5978 struct hostent *h;
5979 struct protoent *p;
5980 struct sockaddr_in6 addr;
5981
5982 p = getprotobyname("TCP");
5983 if(!p) return -1;
5984
5985 sock = socket(AF_INET6, SOCK_STREAM, p->p_proto);
5986 if(sock == -1)
5987 {
5988 perror("socket");
5989 return -1;
5990 }
5991 endprotoent();
5992
5993 fd_flags = fcntl(sock, F_GETFL, 0);
5994 #if defined(O_NONBLOCK)
5995 fd_flags |= O_NONBLOCK;
5996 #elif defined(O_NDELAY)
5997 fd_flags |= O_NDELAY;
5998 #elif defined(FNDELAY)
5999 fd_flags |= O_FNDELAY;
6000 #endif
6001 if (fcntl(sock, F_SETFL, fd_flags) == -1)
6002 {
6003 perror("setsockopt/fcntl");
6004 close(sock);
6005 return -1;
6006 }
6007 addr.sin6_port=htons(port);
6008 addr.sin6_family=AF_INET6;
6009 addr.sin6_flowinfo=0;
6010 addr.sin6_scope_id=IPV6_ADDR_SCOPE_GLOBAL;
6011
6012 h = gethostbyname2(hostname, AF_INET6);
6013 if(h)
6014 {
6015 memcpy(&addr.sin6_addr, h->h_addr, h->h_length);
6016 con = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
6017 perror("con");
6018 }
6019 else if(!h || (con && con != EINPROGRESS))
6020 {
6021 h = gethostbyname2(hostname, AF_INET);
6022 if(h)
6023 {
6024 CREATE_IPV6_MAPPED(&addr.sin6_addr, *((u_int32_t *)h->h_addr_list[0]));
6025 con = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
6026 }
6027 }
6028 endhostent();
6029
6030 if (pTarget)
6031 memcpy(pTarget, &addr, sizeof(*pTarget));
6032
6033 return (!con || (con == -1 && errno == EINPROGRESS))
6034 ? sock
6035 : (close(sock),-1);
6036 } /* open_ipv6_conn() */
6037
6038 #endif /* USE_IPV6 */
6039
6040 /*-------------------------------------------------------------------------*/
6041 static string_t *
6042 lookup_ip_entry (struct in_addr addr, Bool useErq)
6043
6044 /* Lookup the IP address <addr> and return an uncounted pointer to
6045 * a shared string with the hostname. The function looks first in the
6046 * iptable[], then, if not found there and <useErq> is true, asks the ERQ.
6047 * If the hostname can not be found, NULL is returned.
6048 */
6049
6050 {
6051 int i;
6052 string_t *ipname;
6053 struct in_addr tmp;
6054
6055 /* Search for the address backwards from the last added entry,
6056 * hoping that its one of the more recently added ones.
6057 */
6058 i = ipcur;
6059 do {
6060 i--;
6061 if (i < 0)
6062 i += IPSIZE;
6063
6064 if (!memcmp(&(iptable[i].addr.s_addr), &addr.s_addr, sizeof(iptable[i].addr.s_addr))
6065 && iptable[i].name)
6066 {
6067 return iptable[i].name;
6068 }
6069 } while (i != ipcur );
6070
6071 /* The address is new to us.
6072 * Add a temporary entry into the iptable[] to bridge
6073 * the time until the erq has finished the lookup.
6074 * This also handles the case of an unresolvable hostname.
6075 */
6076
6077 iptable[ipcur].addr = addr;
6078 if (iptable[ipcur].name)
6079 free_mstring(iptable[ipcur].name);
6080
6081 memcpy(&tmp, &addr, sizeof(tmp));
6082 #ifndef USE_IPV6
6083 ipname = new_tabled(inet_ntoa(tmp));
6084 #else
6085 ipname = new_tabled(inet6_ntoa(tmp));
6086 #endif
6087
6088 iptable[ipcur].name = ipname;
6089
6090 ipcur = (ipcur+1) % IPSIZE;
6091
6092 /* If we have the erq and may use it, lookup the real hostname */
6093 if (erq_demon >= 0 && useErq)
6094 {
6095 #ifndef USE_IPV6
6096 send_erq(ERQ_HANDLE_RLOOKUP, ERQ_RLOOKUP, (char *)&addr.s_addr, sizeof(addr.s_addr));
6097 #else
6098 send_erq(ERQ_HANDLE_RLOOKUPV6, ERQ_RLOOKUPV6, get_txt(ipname)
6099 , mstrsize(ipname));
6100 #endif
6101 }
6102
6103 return iptable[ipcur].name;
6104 }
6105
6106 #endif /* ERQ_DEMON */
6107
6108 /* End of ERQ Support */
6109 /*=========================================================================*/
6110
6111 /*-------------------------------------------------------------------------*/
6112 void
6113 remove_stale_player_data (void)
6114
6115 /* GC and statistics support: Remove all input_to and prompt infos
6116 * referencing destructed objects.
6117 */
6118
6119 {
6120 int i;
6121
6122 for(i = 0 ; i < MAX_PLAYERS; i++)
6123 {
6124 input_t * ih, * prev;
6125 object_t *ob;
6126
6127 if (all_players[i] == NULL)
6128 continue;
6129
6130 /* Remove stale input_to data */
6131 for ( prev = NULL, ih = all_players[i]->input_handler; ih != NULL; )
6132 if (ih->type == INPUT_TO)
6133 {
6134 input_to_t *tmp = (input_to_t*) ih;
6135 ob = callback_object(&(tmp->fun));
6136 if (ob)
6137 {
6138 prev = ih;
6139 ih = ih->next;
6140 }
6141 else
6142 {
6143 /* The object has selfdestructed */
6144
6145 if (prev == NULL)
6146 {
6147 set_noecho(all_players[i]
6148 , ih->next ? ih->next->noecho : 0
6149 , ih->next ? ih->next->local : MY_FALSE
6150 , MY_TRUE);
6151 all_players[i]->input_handler = ih->next;
6152 }
6153 else
6154 {
6155 prev->next = ih->next;
6156 }
6157
6158 ih = ih->next;
6159
6160 free_input_to(tmp);
6161 }
6162 }
6163 else
6164 {
6165 prev = ih;
6166 ih = ih->next;
6167 }
6168
6169 /* Remove stale snooping monsters */
6170 ob = all_players[i]->snoop_by;
6171 if (ob && !O_IS_INTERACTIVE(ob) && !check_object(ob))
6172 {
6173 free_object(ob, "remove_stale_player_data");
6174 all_players[i]->snoop_by = NULL;
6175 }
6176
6177 /* Remove a stale modify_command object */
6178 ob = all_players[i]->modify_command;
6179 if (ob && !check_object(ob))
6180 {
6181 free_object(ob, "remove_stale_player_data");
6182 all_players[i]->modify_command = NULL;
6183 }
6184 } /* for (i) */
6185 } /* remove_stale_player_data() */
6186
6187 /*-------------------------------------------------------------------------*/
6188 size_t
6189 show_comm_status (strbuf_t * sbuf, Bool verbose UNUSED)
6190
6191 /* Return the amount of memory used by the comm module.
6192 */
6193
6194 {
6195 #if defined(__MWERKS__)
6196 # pragma unused(verbose)
6197 #endif
6198 size_t sum;
6199 int i;
6200
6201 remove_stale_player_data();
6202
6203 sum = 0;
6204
6205 for (i = 0; i <= max_player; i++)
6206 {
6207 interactive_t *pl;
6208 input_t *ih;
6209
6210 pl = all_players[i];
6211 if (!pl)
6212 continue;
6213
6214 sum += sizeof(*pl);
6215
6216 for (ih = pl->input_handler; ih != NULL; ih = ih->next)
6217 switch(ih->type)
6218 {
6219 case INPUT_TO:
6220 sum += sizeof(input_to_t);
6221 break;
6222 case INPUT_ED:
6223 sum += ed_buffer_size(ih);
6224 break;
6225 }
6226 }
6227
6228 if (sbuf)
6229 strbuf_addf(sbuf, "Comm structures\t\t\t\t %9zu\n", sum);
6230 return sum;
6231 } /* show_comm_status() */
6232
6233 #ifdef GC_SUPPORT
6234
6235 /*-------------------------------------------------------------------------*/
6236 void
6237 clear_comm_refs (void)
6238
6239 /* GC support: Clear all refs the module might have.
6240 */
6241
6242 {
6243 int i;
6244
6245 for (i = 0; i < MAX_OUTCONN; i++)
6246 {
6247 if (outconn[i].status != ocNotUsed)
6248 {
6249 if (outconn[i].curr_obj)
6250 clear_object_ref(outconn[i].curr_obj);
6251 }
6252 }
6253
6254 #ifdef ERQ_DEMON
6255 for (i = sizeof (pending_erq) / sizeof (*pending_erq); --i >= 0;)
6256 {
6257 clear_ref_in_vector(&pending_erq[i].fun, 1);
6258 }
6259 #endif /* ERQ_DEMON */
6260 } /* clear_comm_refs() */
6261
6262 /*-------------------------------------------------------------------------*/
6263 void
6264 count_comm_refs (void)
6265
6266 /* GC support: count any ref the module has.
6267 */
6268
6269 {
6270 int i;
6271
6272 for (i = 0; i < MAX_OUTCONN; i++)
6273 {
6274 if (outconn[i].status != ocNotUsed)
6275 {
6276 if (outconn[i].curr_obj)
6277 {
6278 svalue_t sv;
6279
6280 put_object(&sv, outconn[i].curr_obj);
6281 count_ref_in_vector(&sv, 1);
6282 }
6283 }
6284 }
6285
6286 #ifdef ERQ_DEMON
6287 for(i = 0; i < IPSIZE; i++) {
6288 if (iptable[i].name)
6289 count_ref_from_string(iptable[i].name);
6290 }
6291
6292 for (i = sizeof (pending_erq) / sizeof (*pending_erq); --i >= 0;)
6293 {
6294 count_ref_in_vector(&pending_erq[i].fun, 1);
6295 }
6296 #endif /* ERQ_DEMON */
6297 } /* count_comm_refs() */
6298
6299 /*-------------------------------------------------------------------------*/
6300 void
6301 clear_input_refs (input_t *i)
6302
6303 /* GC Support: Clear all references from input_t <i>.
6304 */
6305
6306 {
6307 switch (i->type)
6308 {
6309 case INPUT_TO:
6310 {
6311 input_to_t *it = (input_to_t*) i;
6312
6313 clear_ref_in_callback(&(it->fun));
6314 clear_ref_in_vector(&(it->input.prompt), 1);
6315
6316 break;
6317 }
6318 case INPUT_ED:
6319 clear_ed_buffer_refs(i);
6320 break;
6321 }
6322 } /* clear_input_refs() */
6323
6324 /*-------------------------------------------------------------------------*/
6325 void
6326 count_input_refs (input_t *i)
6327
6328 /* GC Support: Count all references from input_t <i>.
6329 */
6330
6331 {
6332 switch (i->type)
6333 {
6334 case INPUT_TO:
6335 {
6336 input_to_t *it = (input_to_t*) i;
6337
6338 count_ref_in_callback(&(it->fun));
6339 count_ref_in_vector(&(it->input.prompt), 1);
6340
6341 break;
6342 }
6343 case INPUT_ED:
6344 count_ed_buffer_refs(i);
6345 break;
6346 }
6347 } /* count_input_refs() */
6348
6349 #endif /* GC_SUPPORT */
6350
6351
6352 /*=========================================================================*/
6353
6354 /*-------------------------------------------------------------------------*/
6355 static svalue_t *
6356 query_ip_name (svalue_t *sp, Bool lookup)
6357
6358 /* Lookup the IP address (<lookup> is false) or IP hostname (<lookup> is
6359 * true) of object <sp> and return it. If <sp> is the number 0 or a
6360 * non-interactive object, the number 0 is returned.
6361 *
6362 * The hostname is read from the iptable[], so if it hasn't been
6363 * resolved yet, we return the number in any case.
6364 *
6365 * If <sp> is a reference to an interactive object, it will be replaced
6366 * on return with an array of integers with the full sockaddr_in:
6367 * array[0.. 1]: sin_family
6368 * array[2.. 3]: sin_port
6369 * array[4.. 7]: sin_addr
6370 * array[8..15]: undefined (ideally 0).
6371 *
6372 * The function is used to implement the efuns query_ip_number() and
6373 * query_ip_name().
6374 */
6375
6376 {
6377 object_t *ob;
6378 int i;
6379 interactive_t *ip;
6380 string_t *str;
6381
6382 /* Set <ob> to the object passed on the stack. */
6383
6384 if (sp->type != T_OBJECT)
6385 {
6386 svalue_t *svp;
6387
6388 if (sp->type == T_NUMBER && !sp->u.number)
6389 return sp;
6390 svp = sp;
6391 while (svp->type == T_LVALUE || svp->type == T_PROTECTED_LVALUE)
6392 svp = svp->u.lvalue;
6393 if (svp->type != T_OBJECT)
6394 {
6395 errorf("Bad arg 1 to query_ip_number(): expected object/object&, got %s&.\n"
6396 , typename(svp->type));
6397 /* NOTREACHED */
6398 }
6399 ob = svp->u.ob;
6400 }
6401 else
6402 {
6403 ob = sp->u.ob;
6404 deref_object(ob, "query_ip_name");
6405 sp->type = T_INVALID;
6406 }
6407
6408 /* Return 0 for non-interactive objects */
6409 if (!(O_SET_INTERACTIVE(ip, ob)))
6410 {
6411 free_svalue(sp);
6412 put_number(sp, 0);
6413 return sp;
6414 }
6415
6416 /* If the object was passed as reference, replace it with an array
6417 * with the full sockaddr_in.
6418 */
6419 if (sp->type == T_LVALUE)
6420 {
6421 svalue_t array, *svp;
6422 vector_t *v;
6423 char *cp;
6424
6425 v = allocate_array(sizeof ip->addr);
6426 if (v)
6427 {
6428 put_array(&array, v);
6429 i = sizeof ip->addr;
6430 svp = v->item;
6431 cp = (char *)&ip->addr;
6432 do {
6433 svp->u.number = *cp++;
6434 svp++;
6435 } while(--i);
6436 transfer_svalue(sp, &array);
6437 }
6438 else
6439 {
6440 assign_svalue(sp, &const0);
6441 }
6442
6443 return sp;
6444 }
6445
6446 /* If the hostname is requested and we indeed have it in our table,
6447 * return it.
6448 */
6449 if (lookup)
6450 {
6451 #ifdef ERQ_DEMON
6452 string_t * hname;
6453
6454 hname = lookup_ip_entry(ip->addr.sin_addr, MY_FALSE);
6455 if (hname)
6456 {
6457 put_ref_string(sp, hname);
6458 return sp;
6459 }
6460 #else
6461 /* The if(lookup) gets rid of a 'lookup unused' warning. */
6462 #endif
6463 }
6464
6465 /* Return the IP address as string.
6466 */
6467
6468 #ifndef USE_IPV6
6469 str = new_mstring(inet_ntoa(ip->addr.sin_addr));
6470 #else
6471 str = new_mstring(inet6_ntoa(ip->addr.sin_addr));
6472 #endif
6473 if (!str)
6474 {
6475 inter_sp = sp - 1;
6476 errorf("Out of memory for IP address\n");
6477 }
6478 put_string(sp, str);
6479 return sp;
6480 } /* query_ip_number() */
6481
6482 /*-------------------------------------------------------------------------*/
6483 char *
6484 query_host_name (void)
6485
6486 /* Return the hostname (and just the hostname, not the full domain name).
6487 * The result is a pointer to a static array!
6488 * Called by lex.c, main.c and swap.c .
6489 */
6490
6491 {
6492 return host_name;
6493 } /* query_host_name() */
6494
6495 /*-------------------------------------------------------------------------*/
6496 char *
6497 get_host_ip_number (void)
6498
6499 /* Return the IP address of the host.
6500 * The result is a newly allocated string.
6501 * Called by lex.c .
6502 */
6503
6504 {
6505 #ifndef USE_IPV6
6506 char buf[INET_ADDRSTRLEN+3];
6507
6508 sprintf(buf, "\"%s\"", inet_ntoa(host_ip_number));
6509 #else
6510 char buf[INET6_ADDRSTRLEN+3];
6511
6512 sprintf(buf, "\"%s\"", inet6_ntoa(host_ip_number));
6513 #endif
6514 return string_copy(buf);
6515 } /* query_host_ip_number() */
6516
6517 /*-------------------------------------------------------------------------*/
6518 svalue_t *
6519 f_query_snoop (svalue_t *sp)
6520
6521 /* EFUN: query_snoop()
6522 *
6523 * object query_snoop(object victim)
6524 *
6525 * Return the object which is snooping <victim>, or 0 if there is none.
6526 * The call must be allowed by master->valid_query_snoop().
6527 */
6528
6529 {
6530 svalue_t *arg1;
6531 object_t *ob;
6532
6533 /* Do some test and set ob to the snooper (if any) */
6534 switch (0) /* try {...} */
6535 {
6536 default:
6537 ob = sp->u.ob;
6538 if ((ob->flags & (O_DESTRUCTED|O_SHADOW)) != O_SHADOW
6539 || O_GET_SHADOW(ob)->ip == NULL)
6540 {
6541 zero_object_svalue(sp);
6542 return sp;
6543 }
6544 inter_sp = sp;
6545 assert_master_ob_loaded();
6546 if (current_object != master_ob)
6547 {
6548 assign_eval_cost();
6549 arg1 = apply_master(STR_VALID_QSNOOP, 1);
6550 if (arg1 == 0 || arg1->type != T_NUMBER || !arg1->u.number)
6551 {
6552 ob = NULL;
6553 break;
6554 }
6555 }
6556 else
6557 {
6558 deref_object(ob, "query_snoop");
6559 }
6560 ob = O_GET_INTERACTIVE(ob)->snoop_by;
6561 }
6562
6563 /* Return the result */
6564 if (ob)
6565 put_ref_object(sp, ob, "query_snoop");
6566 else
6567 put_number(sp, 0);
6568 return sp;
6569 } /* f_query_snoop() */
6570
6571 /*-------------------------------------------------------------------------*/
6572 svalue_t *
6573 f_query_idle (svalue_t *sp)
6574
6575 /* EFUN: query_idle()
6576 *
6577 * int query_idle(object ob)
6578 *
6579 * Return how many seconds a user object has been idle.
6580 */
6581
6582 {
6583 int i;
6584 object_t *ob;
6585
6586 ob = sp->u.ob;
6587 if (!O_IS_INTERACTIVE(ob))
6588 {
6589 inter_sp = sp;
6590 errorf("query_idle() of non-interactive object.\n");
6591 return sp;
6592 }
6593
6594 i = current_time - O_GET_INTERACTIVE(ob)->last_time;
6595 deref_object(ob, "query_idle");
6596 put_number(sp, i);
6597 return sp;
6598 } /* f_query_idle() */
6599
6600 /*-------------------------------------------------------------------------*/
6601 svalue_t *
6602 f_remove_interactive (svalue_t *sp)
6603
6604 /* EFUN: remove_interactive()
6605 *
6606 * void remove_interactive(object ob)
6607 *
6608 * Close the connection to the interactive object ob.
6609 *
6610 * In fact, the connection is only flushed and marked for closing,
6611 * as a remove_interactive() here can upset some other code.
6612 * The actual remove will be done by get_message().
6613 */
6614
6615 {
6616 interactive_t *victim;
6617
6618 if (O_SET_INTERACTIVE(victim, sp->u.ob)
6619 && !victim->closing
6620 && !victim->do_close)
6621 {
6622 if (victim->message_length) {
6623 command_giver = victim->ob;
6624 add_message(message_flush);
6625
6626 /* message_flush takes always directly effect on the
6627 * socket. No apply() is involved.
6628 */
6629 }
6630 victim->do_close = FLAG_DO_CLOSE;
6631 }
6632 free_svalue(sp);
6633 return sp - 1;
6634 } /* f_remove_interactive() */
6635
6636 /*-------------------------------------------------------------------------*/
6637 #ifdef DEBUG
6638
6639 void
6640 count_comm_extra_refs (void)
6641
6642 /* Count all the refs to verify the normal refcounting. */
6643
6644 {
6645 int i;
6646
6647 #ifdef ERQ_DEMON
6648 for (i = sizeof(pending_erq) / sizeof(*pending_erq); --i >= 0; )
6649 count_extra_ref_in_vector(&pending_erq[i].fun, 1);
6650 #endif /* ERQ_DEMON */
6651
6652 for (i = 0; i < MAX_PLAYERS; i++)
6653 {
6654 object_t *ob;
6655 input_t *ih;
6656
6657 if (all_players[i] == 0)
6658 continue;
6659 all_players[i]->ob->extra_ref++;
6660 if ( NULL != (ob = all_players[i]->snoop_by) ) {
6661 interactive_t *ip;
6662
6663 if (!(O_SET_INTERACTIVE(ip, ob)))
6664 {
6665 /* snooping monster */
6666 ob->extra_ref++;
6667 }
6668 } /* end of snoop-processing */
6669
6670 for ( ih = all_players[i]->input_handler; ih; ih = ih->next)
6671 switch(ih->type)
6672 {
6673 case INPUT_TO:
6674 {
6675 input_to_t *it = (input_to_t*) ih;
6676 count_callback_extra_refs(&(it->fun));
6677 count_extra_ref_in_vector(&it->input.prompt, 1);
6678 break;
6679 }
6680 case INPUT_ED:
6681 count_ed_buffer_extra_refs(ih);
6682 break;
6683 }
6684
6685 if ( NULL != (ob = all_players[i]->modify_command) )
6686 count_extra_ref_in_object(ob);
6687 count_extra_ref_in_vector(&all_players[i]->prompt, 1);
6688 }
6689 } /* count_comm_extra_refs() */
6690
6691 #endif /* DEBUG */
6692
6693 /*-------------------------------------------------------------------------*/
6694 svalue_t *
6695 f_send_udp (svalue_t *sp)
6696
6697 /* EFUN: send_udp()
6698 *
6699 * int send_udp(string host, int port, string message)
6700 * int send_udp(string host, int port, int * message)
6701 *
6702 * Sends The message in an UDP packet to the given host and port
6703 * number. Causes a privilege violation.
6704 * The message can be given either as string, or as array of
6705 * bytes. The latter variant allows to send binary data as well.
6706 * Returns 1 on success, 0 on failure.
6707 *
6708 * Note: On some machines a failed send_imp() will not be registered
6709 * until the next send_imp() - the latter one might return '0' even
6710 * if itself was successful.
6711 */
6712
6713 {
6714 char *to_host = NULL;
6715 int to_port;
6716 char *msg;
6717 size_t msglen;
6718 #ifndef USE_IPV6
6719 int ip1, ip2, ip3, ip4;
6720 #endif /* USE_IPV6 */
6721 struct sockaddr_in name;
6722 struct hostent *hp;
6723 int ret = 0;
6724 svalue_t *firstarg; /* store the first argument */
6725
6726 firstarg = sp-2; /* hostname */
6727
6728 switch(0) { default: /* try {...} */
6729
6730 /* Set msg/msglen to the data of the message to send */
6731
6732 if (sp->type == T_STRING)
6733 {
6734 msg = get_txt(sp->u.str);
6735 msglen = mstrsize(sp->u.str);
6736 }
6737 else /* it's an array */
6738 {
6739 vector_t *v;
6740 svalue_t *svp;
6741 char *cp;
6742 p_int j;
6743
6744 v = sp->u.vec;
6745 msglen = VEC_SIZE(v);
6746 /* allocate memory and push error handler onto stack */
6747 cp = msg = xalloc_with_error_handler(msglen);
6748 if (!msg) {
6749 errorf("Out of memory (%zu bytes) in send_udp() for "
6750 "temporary buffer.\n", msglen);
6751 }
6752 sp = inter_sp;
6753
6754 svp = &v->item[0];
6755 for (j = (p_int)msglen; --j >= 0; )
6756 *cp++ = (char)(*svp++).u.number;
6757 }
6758
6759 /* Is this call valid? */
6760
6761 if (!privilege_violation(STR_SEND_UDP, firstarg, sp))
6762 break;
6763
6764 if (udp_s < 0)
6765 break;
6766
6767 /* Determine the destination address */
6768
6769 {
6770 size_t adrlen;
6771
6772 adrlen = mstrsize(firstarg->u.str);
6773 /* as there are no runtime error raised below, we just xallocate
6774 * and don't bother with an error handler. */
6775 to_host = xalloc(adrlen+1);
6776 if (!to_host)
6777 {
6778 errorf("Out of memory (%zu bytes) in send_udp() for host address\n"
6779 , (adrlen+1));
6780 /* NOTREACHED */
6781 }
6782 memcpy(to_host, get_txt(firstarg->u.str), adrlen);
6783 to_host[adrlen] = '\0';
6784 }
6785 to_port = (sp-1)->u.number;
6786
6787 #ifndef USE_IPV6
6788 if (sscanf(to_host, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) == 4)
6789 {
6790 name.sin_addr.s_addr = inet_addr(to_host);
6791 name.sin_family = AF_INET;
6792 }
6793 else
6794 {
6795 /* TODO: Uh-oh, blocking DNS in the execution thread */
6796 hp = gethostbyname(to_host);
6797 if (hp == 0)
6798 break;
6799 memcpy(&name.sin_addr, hp->h_addr, (size_t)hp->h_length);
6800 name.sin_family = AF_INET;
6801 }
6802
6803 #else /* USE_IPV6 */
6804
6805 /* TODO: Uh-oh, blocking DNS in the execution thread */
6806 hp = gethostbyname2(to_host, AF_INET6);
6807 if (hp == 0) hp = gethostbyname2(to_host, AF_INET);
6808 if (hp == 0) break;
6809 memcpy(&name.sin_addr, hp->h_addr, (size_t)hp->h_length);
6810
6811 if (hp->h_addrtype == AF_INET)
6812 {
6813 CREATE_IPV6_MAPPED(&name.sin_addr, (u_int32_t)hp->h_addr_list[0]);
6814 }
6815 name.sin_family = AF_INET6;
6816 #endif /* USE_IPV6 */
6817
6818 name.sin_port = htons(to_port);
6819
6820 /* Send the message. */
6821 #ifndef SENDTO_BROKEN
6822 if (sendto(udp_s, msg, msglen, 0,
6823 (struct sockaddr *)&name, sizeof(name)) != (int)msglen)
6824 #endif
6825 break;
6826 ret = 1;
6827 }
6828 /* Cleanup - an allocated buffer for the message will be on the stack
6829 * above the arguments, therefore clean everything from the first argument
6830 * (including) to sp.
6831 */
6832 sp = pop_n_elems((sp-firstarg)+1, sp);
6833 xfree(to_host);
6834
6835 /*Return the result */
6836 sp++;
6837 put_number(sp, ret);
6838 return sp;
6839
6840 } /* f_send_udp() */
6841
6842 /*-------------------------------------------------------------------------*/
6843 svalue_t *
6844 f_set_buffer_size (svalue_t *sp)
6845
6846 /* EFUN: set_buffer_size()
6847 *
6848 * int set_buffer_size(int size)
6849 *
6850 * Changes the socket buffer size for this_interactive() to size,
6851 * up to a preconfigured maximum, result is the old buffer size
6852 * (or -1 on systems which aren't able to change the socket
6853 * buffer).
6854 * Modifying the buffer size may result in a better IO
6855 * throughput, but can also worsen it.
6856 */
6857
6858 {
6859 int new;
6860
6861 /* Get the desired buffer size */
6862
6863 if (sp->u.number > SET_BUFFER_SIZE_MAX)
6864 {
6865 errorf("Bad arg 1 to set_buffer_size(): value %"PRIdPINT" exceeds maximum %ld\n"
6866 , sp->u.number, (long) SET_BUFFER_SIZE_MAX);
6867 /* NOTREACHED */
6868 return sp;
6869 }
6870 new = sp->u.number;
6871
6872 sp->u.number = -1; /* Default result */
6873
6874 #ifdef SO_SNDBUF
6875 {
6876 int old;
6877 length_t optlen;
6878 interactive_t *ip;
6879
6880 if (!(O_SET_INTERACTIVE(ip, current_object))
6881 || ip->do_close)
6882 {
6883 return sp;
6884 }
6885
6886
6887 optlen = sizeof old;
6888 if (getsockopt(ip->socket, SOL_SOCKET, SO_SNDBUF, (char *)&old, &optlen) < 0)
6889 return sp;
6890 if (setsockopt(ip->socket, SOL_SOCKET, SO_SNDBUF, (char *)&new, sizeof new) < 0)
6891 return sp;
6892 sp->u.number = old;
6893 }
6894 #endif /* SO_SNDBUF */
6895
6896 return sp;
6897 } /* f_set_buffer_size() */
6898
6899 /*-------------------------------------------------------------------------*/
6900 svalue_t *
6901 f_binary_message (svalue_t *sp)
6902
6903 /* EFUN: binary_message()
6904 *
6905 * int binary_message(int *|string message, int flags)
6906 *
6907 * Flush output and send output directly with write WITHOUT IAC QUOTING.
6908 * The message may contain zeroes if given as int *.
6909 * The messages goes to this_object(), but only if interactive.
6910 * Returned value: number of characters actually written.
6911 * Any 'allowed charset' setting is ignored.
6912 *
6913 * Flag settings are interpreted bitwise and may be ored
6914 * together:
6915 *
6916 * Bit 0 (value 1): when set, add_message() is used instead of
6917 * write(). Thus no previous flushing of the buffer is
6918 * needed, but the output is not immediate, nor can the
6919 * number of bytes actually sent be determined - the return
6920 * value is undefined.
6921 * Bit 1 (value 2): The buffer is flushed _after_ adding the
6922 * message. Useful only in conjunction with Bit 0.
6923 *
6924 * The idea behind the flag settings is that sending command
6925 * codes for colours and other things needs to bypass the allowed
6926 * charset filters, but isn't important enough to waste bandwith
6927 * on a synchronous transmission.
6928 */
6929
6930 {
6931 string_t *msg;
6932 mp_int wrote = 0, i;
6933 svalue_t *svp;
6934 interactive_t *ip;
6935 object_t *save_command_giver;
6936
6937 /* Set message to the data to be sent, and size to its length. */
6938
6939 if (sp[-1].type == T_POINTER)
6940 {
6941 char *p;
6942 size_t size;
6943
6944 size = VEC_SIZE(sp[-1].u.vec);
6945 msg = alloc_mstring(size);
6946 if (!msg)
6947 errorf("Out of memory (%zu bytes) in binary_message()",size);
6948 for (i = (mp_int)size, svp = sp[-1].u.vec->item, p = get_txt(msg)
6949 ; --i >= 0; svp++)
6950 {
6951 if (svp->type != T_NUMBER)
6952 {
6953 free_mstring(msg);
6954 errorf("Bad arg 1 to binary_message(): got %s*, "
6955 "expected string/int*.\n", typename(svp->type));
6956 /* NOTREACHED */
6957 return sp;
6958 }
6959 *p++ = (char)svp->u.number;
6960 }
6961 }
6962 else /* it's a string */
6963 {
6964 msg = ref_mstring(sp[-1].u.str);
6965 }
6966
6967 /* Send the message */
6968
6969 i = 0;
6970 if (O_SET_INTERACTIVE(ip, current_object)
6971 && !ip->do_close)
6972 {
6973 save_command_giver = command_giver;
6974 command_giver = current_object;
6975
6976 if (sp->u.number & 1)
6977 {
6978 /* Write before flush... */
6979
6980 sending_telnet_command = MY_TRUE; /* turn of IAC quoting */
6981
6982 add_message(FMT_STRING, msg);
6983
6984 sending_telnet_command = MY_FALSE;
6985
6986 if (sp->u.number & 2)
6987 add_message(message_flush);
6988
6989 wrote = mstrsize(msg);
6990 }
6991 else
6992 {
6993 /* Flush, then write. */
6994 add_message(message_flush);
6995
6996 /* Since all pending data was flushed, we can write directly
6997 * to the socket now.
6998 */
6999
7000 if (comm_socket_write(get_txt(msg), mstrsize(msg), ip, 0))
7001 wrote = mstrsize(msg);
7002
7003 } /* if (type of write) */
7004
7005 command_giver = save_command_giver;
7006 } /* end if interactive */
7007
7008 sp--;
7009 free_mstring(msg);
7010 free_svalue(sp);
7011 put_number(sp, wrote);
7012 return sp;
7013 } /* f_binary_message() */
7014
7015 /*-------------------------------------------------------------------------*/
7016 svalue_t *
7017 f_exec (svalue_t *sp)
7018
7019 /* EFUN exec()
7020 *
7021 * object exec(object new, object old)
7022 *
7023 * Switch the network connection from <old> to <new>. If <new> is already
7024 * interactive, its connection will be switched to <old>.
7025 *
7026 * It is used to load different "user objects" or to reconnect
7027 * link dead users.
7028 *
7029 * If <old> was command_giver, <news> will be the new command_giver.
7030 *
7031 * The call is validated by master->valid_exec() and returns 0 on
7032 * failure, and 1 on success.
7033 */
7034
7035 {
7036 int rc;
7037 object_t *ob;
7038 object_t *obfrom;
7039
7040 rc = 0;
7041
7042 ob = sp[-1].u.ob;
7043 obfrom = sp[0].u.ob;
7044
7045 do {
7046 svalue_t *v;
7047 interactive_t *stale_interactive, *ip;
7048 object_t *save_command;
7049
7050 /* Ask the master if this exec() is ok. */
7051 push_ref_string(inter_sp, current_prog->name);
7052 /* TODO: FinalFrontier suggests 'current_object->prog->name' */
7053 push_ref_object(inter_sp, ob, "exec");
7054 push_ref_object(inter_sp, obfrom, "exec");
7055 v = apply_master(STR_VALID_EXEC, 3);
7056 if (!v || v->type != T_NUMBER || v->u.number == 0)
7057 break;
7058
7059 /* stale_interactive becomes the former interactive _if_ it
7060 * still is an interactive_t.
7061 */
7062 if (!(O_SET_INTERACTIVE(stale_interactive, ob)))
7063 {
7064 stale_interactive = NULL;
7065 }
7066
7067 if (!(O_SET_INTERACTIVE(ip, obfrom)))
7068 errorf("Bad argument 2 to exec(): not interactive.\n");
7069
7070 /* When we have to have an out of memory error, have it before pointers
7071 * get changed.
7072 */
7073 assert_shadow_sent(ob);
7074
7075 save_command = command_giver;
7076
7077 /* If <ob> has a connection, flush it */
7078 if (stale_interactive)
7079 {
7080 if (stale_interactive->message_length)
7081 {
7082 command_giver = ob;
7083 add_message(message_flush);
7084 }
7085 }
7086
7087 /* Flush the connection of <obfrom> */
7088
7089 if (ip->message_length) {
7090 command_giver = obfrom;
7091 add_message(message_flush);
7092 }
7093 command_giver = save_command;
7094
7095 /* Switch a possible snooper */
7096
7097 if (ip->snoop_on)
7098 ip->snoop_on->snoop_by = ob;
7099
7100 /* Switch the interactive */
7101
7102 O_GET_INTERACTIVE(ob) = ip;
7103 O_GET_INTERACTIVE(obfrom) = NULL;
7104 ob->flags |= O_ONCE_INTERACTIVE;
7105 ip->ob = ob;
7106 ip->catch_tell_activ = MY_TRUE;
7107
7108 if (stale_interactive)
7109 {
7110 /* Tie <ob>s stale connection to <obfrom>. */
7111
7112 O_GET_INTERACTIVE(obfrom) = stale_interactive;
7113 stale_interactive->ob = obfrom;
7114 if (stale_interactive->snoop_on)
7115 stale_interactive->snoop_on->snoop_by = obfrom;
7116 stale_interactive->catch_tell_activ = MY_TRUE;
7117 }
7118 else
7119 {
7120 /* Clean up <obfrom> after the loss of connection */
7121
7122 obfrom->flags &= ~O_ONCE_INTERACTIVE;
7123 check_shadow_sent(obfrom);
7124
7125 ref_object(ob, "exec");
7126 free_object(obfrom, "exec");
7127 }
7128
7129 /* If this_player() or this_interactive() point to one of the
7130 * involved objects, switch it too.
7131 */
7132 if (obfrom == command_giver)
7133 command_giver = ob;
7134 else if (ob == command_giver)
7135 command_giver = obfrom;
7136
7137 if (obfrom == current_interactive)
7138 current_interactive = ob;
7139 else if (ob == current_interactive)
7140 current_interactive = obfrom;
7141
7142 rc = 1;
7143 }while(0);
7144
7145 free_svalue(sp--);
7146 free_svalue(sp); /* object might have been destructed */
7147 put_number(sp, rc);
7148
7149 return sp;
7150 } /* f_exec() */
7151
7152 /*-------------------------------------------------------------------------*/
7153 svalue_t *
7154 f_interactive (svalue_t *sp)
7155
7156 /* EFUN interactive()
7157 *
7158 * int interactive(object ob)
7159 *
7160 * Return non-zero if ob, or when the argument is omitted, this
7161 * object(), is an interactive user. Will return 1 if the
7162 * object is interactive, else 0.
7163 */
7164
7165 {
7166 int i;
7167 object_t *ob;
7168 interactive_t *ip;
7169
7170 ob = sp->u.ob;
7171 (void)O_SET_INTERACTIVE(ip, ob);
7172 i = ip && !ip->do_close;
7173 deref_object(ob, "interactive");
7174 put_number(sp, i);
7175
7176 return sp;
7177 } /* f_interactive() */
7178
7179 /*-------------------------------------------------------------------------*/
7180 svalue_t *
7181 v_input_to (svalue_t *sp, int num_arg)
7182
7183 /* EFUN input_to()
7184 *
7185 * void input_to(string fun)
7186 * void input_to(string fun, int flag, ...)
7187 *
7188 * Enable next line of user input to be sent to the local
7189 * function fun as an argument. The input line will not be
7190 * parsed, only when it starts with a "!" (like a kind of shell
7191 * escape) (this feature may be disabled).
7192 * The function <fun> may be static, but must not be private (or
7193 * it won't be found).
7194 *
7195 * Note that fun is not called immediately but after pressing the
7196 * RETURN key.
7197 *
7198 * If input_to() is called more than once in the same execution,
7199 * only the first call has any effect.
7200 *
7201 * The optional 3rd and following args will be passed as second and
7202 * subsequent args to the function fun. (This feature is was
7203 * added only recently, to avoid the need for global variables)
7204 */
7205
7206 {
7207 svalue_t *arg; /* Pointer to the arguments of the efun */
7208 svalue_t *extra_arg; /* Pointer to the extra arguments of the efun */
7209 int iflags; /* The flags passed to input_to() */
7210 int flags; /* The flags as required for .noecho */
7211 input_to_t *it;
7212 int extra; /* Number of extra arguments */
7213 int error_index;
7214
7215 arg = sp - num_arg + 1;
7216
7217 /* Extract the arguments */
7218
7219 iflags = 0;
7220 extra = 0;
7221 extra_arg = arg + 1;
7222
7223 if (arg[0].type != T_CLOSURE && arg[0].type != T_STRING)
7224 {
7225 vefun_bad_arg(1, sp);
7226 /* NOTREACHED */
7227 return NULL;
7228 }
7229
7230 if (num_arg > 1)
7231 {
7232 if (arg[1].type != T_NUMBER)
7233 {
7234 vefun_bad_arg(2, sp);
7235 /* NOTREACHED */
7236 return NULL;
7237 }
7238
7239 iflags = arg[1].u.number;
7240 extra = num_arg - 2;
7241 extra_arg = arg + 2;
7242 }
7243
7244 {
7245 interactive_t *ip;
7246
7247 if (command_giver != NULL
7248 && O_SET_INTERACTIVE(ip, command_giver)
7249 && !ip->tn_enabled
7250 )
7251 {
7252 if (!(iflags & INPUT_NOECHO) != !(ip->noecho & NOECHO_MASK))
7253 {
7254 warnf("input_to(): Change in NOECHO mode requested for object '%s' "
7255 "with telnet disabled.\n"
7256 , get_txt(command_giver->name)
7257 );
7258 }
7259
7260 if (!(iflags & INPUT_CHARMODE) != !(ip->noecho & CHARMODE_MASK)
7261 && (iflags & INPUT_NO_TELNET) == 0
7262 )
7263 {
7264 warnf("input_to(): Change in CHARMODE mode requested for object '%s' "
7265 "with telnet disabled.\n"
7266 , get_txt(command_giver->name)
7267 );
7268 }
7269 }
7270 }
7271
7272 /* Setup the flags required for 'noecho' */
7273 flags = ((iflags & INPUT_NOECHO) ? NOECHO_REQ : 0)
7274 | ((iflags & INPUT_CHARMODE) ? CHARMODE_REQ : 0)
7275 | ((iflags & INPUT_IGNORE_BANG) ? IGNORE_BANG : 0)
7276 ;
7277
7278 /* Check the arguments */
7279
7280 if (iflags & INPUT_PROMPT)
7281 {
7282 if (num_arg <= 2)
7283 {
7284 errorf("Missing prompt argument to input_to().\n");
7285 /* NOTREACHED */
7286 }
7287
7288 if (arg[2].type != T_STRING && arg[2].type != T_CLOSURE)
7289 {
7290 vefun_bad_arg(3, sp);
7291 /* NOTREACHED */
7292 }
7293 }
7294
7295 if ((flags & IGNORE_BANG)
7296 && !privilege_violation4(STR_INPUT_TO, command_giver, 0, flags, sp))
7297 {
7298 do
7299 {
7300 free_svalue(sp--);
7301 } while (--num_arg);
7302
7303 put_number(arg, 0); /* arg should equal sp+1 */
7304 return arg;
7305 }
7306
7307 /* There is a chance that the privilege_violation() method destructed
7308 * the current object or the command_giver - return as if the call was
7309 * denied.
7310 */
7311 if (!check_object(current_object) || !check_object(command_giver))
7312 {
7313 do
7314 {
7315 free_svalue(sp--);
7316 } while (--num_arg);
7317
7318 put_number(arg, 0); /* arg should equal sp+1 */
7319 return arg;
7320 }
7321
7322 /* Allocate and setup the input_to structure */
7323
7324 xallocate(it, sizeof *it, "new input_to");
7325 init_empty_callback(&(it->fun));
7326 put_number(&(it->input.prompt), 0);
7327
7328 /* If SET_PROMPT was specified, collect it */
7329
7330 if (iflags & INPUT_PROMPT)
7331 {
7332 transfer_svalue(&(it->input.prompt), arg+2);
7333 extra--;
7334 extra_arg++;
7335 }
7336
7337 /* Parse the extra args for the call */
7338
7339 if (arg[0].type == T_STRING)
7340 {
7341 error_index = setup_function_callback(&(it->fun), current_object
7342 , arg[0].u.str
7343 , extra, extra_arg
7344 , MY_TRUE
7345 );
7346 free_string_svalue(arg);
7347 }
7348 else if (arg[0].type == T_CLOSURE)
7349 error_index = setup_closure_callback(&(it->fun), arg
7350 , extra, extra_arg
7351 , MY_TRUE
7352 );
7353 else
7354 error_index = 1;
7355
7356 if (error_index >= 0)
7357 {
7358 free_input_to(it);
7359 vefun_bad_arg(error_index + num_arg - extra + 1, arg-1);
7360 /* NOTREACHED */
7361 return arg-1;
7362 }
7363
7364 /* At this point the call back should be bound to an existing object - but
7365 * as a sanity check we test it.
7366 */
7367 if (NULL == callback_object(&(it->fun)))
7368 {
7369 free_input_to(it);
7370 put_number(arg, 0); /* arg should equal sp+1 */
7371 return arg;
7372 }
7373
7374 /* Try setting the input_to. On success, return 1. */
7375
7376 if (set_call( command_giver, it, (char)flags
7377 , (iflags & INPUT_NO_TELNET) != 0
7378 , (iflags & INPUT_APPEND) != 0
7379 )
7380 )
7381 {
7382 put_number(arg, 1);
7383 return arg;
7384 }
7385
7386 /* input_to() was not allowed - return 0. */
7387
7388 free_input_to(it);
7389 put_number(arg, 0);
7390 return arg;
7391 } /* v_input_to() */
7392
7393 /*-------------------------------------------------------------------------*/
7394 static void
7395 free_input_to (input_to_t *it)
7396
7397 /* Deallocate the input_to structure <it> and all referenced memory.
7398 */
7399
7400 {
7401 free_callback(&(it->fun));
7402 free_svalue(&(it->input.prompt));
7403 xfree(it);
7404 } /* free_input_to() */
7405
7406 /*-------------------------------------------------------------------------*/
7407 static void
7408 free_input_handler (input_t *ih)
7409
7410 /* Deallocate the input_t structure <ih> and all referenced memory.
7411 */
7412
7413 {
7414 switch (ih->type)
7415 {
7416 case INPUT_TO:
7417 free_input_to((input_to_t*) ih);
7418 break;
7419
7420 case INPUT_ED:
7421 free_ed_buffer(ih);
7422 break;
7423 }
7424
7425 } /* free_input_handler() */
7426
7427 /*-------------------------------------------------------------------------*/
7428 void
7429 abort_input_handler (interactive_t *ip)
7430
7431 /* Called from destruct_object to finish some input handlers,
7432 * specifically save all ed sessions.
7433 */
7434 {
7435 input_t ** ptr = &(ip->input_handler);
7436
7437 while (*ptr)
7438 {
7439 switch ((*ptr)->type)
7440 {
7441 case INPUT_ED:
7442 {
7443 input_t * ed_buf = *ptr;
7444
7445 *ptr = (*ptr)->next;
7446 save_ed_buffer(ed_buf);
7447 break;
7448 }
7449
7450 default:
7451 ptr = &((*ptr)->next);
7452 break;
7453 }
7454 }
7455 } /* abort_input_handler() */
7456
7457 /*-------------------------------------------------------------------------*/
7458 void
7459 add_input_handler (interactive_t *ip, input_t *ih, Bool append)
7460
7461 /* Put the input handler <ih> in front of the input handler list of
7462 * the interactive <ip>.
7463 * If <append> is TRUE, the handler is appended to the list.
7464 */
7465 {
7466 if (!append || ip->input_handler == NULL)
7467 {
7468 ih->next = ip->input_handler;
7469 ip->input_handler = ih;
7470 }
7471 else
7472 {
7473 input_t * ptr = ip->input_handler;
7474
7475 while (ptr->next != NULL)
7476 ptr = ptr->next;
7477
7478 ptr->next = ih;
7479 ih->next = NULL;
7480 }
7481
7482 if (ih->noecho || ip->noecho)
7483 set_noecho(ip, ih->noecho, ih->local, MY_FALSE);
7484
7485 } /* add_input_handler() */
7486
7487 /*-------------------------------------------------------------------------*/
7488 void
7489 remove_input_handler (interactive_t *ip, input_t *ih)
7490
7491 /* Remove the input handler <ih> from the input handler list of
7492 * the interactive <ip>. <ih> is not freed.
7493 */
7494 {
7495 input_t * ptr = ip->input_handler;
7496
7497 if (ptr == ih)
7498 {
7499 ip->input_handler = ih->next;
7500 return;
7501 }
7502
7503 while (ptr)
7504 {
7505 if (ptr->next == ih)
7506 {
7507 ptr->next = ih->next;
7508 break;
7509 }
7510 ptr = ptr->next;
7511 }
7512
7513 } /* remove_input_handler() */
7514
7515 /*-------------------------------------------------------------------------*/
7516 input_t *
7517 get_input_handler (interactive_t *ip, input_type_t type)
7518
7519 /* Returns the first input handler from <ip> of type <type>.
7520 */
7521 {
7522 input_t *ih;
7523
7524 for (ih = ip->input_handler; ih; ih = ih->next)
7525 if (ih->type == type)
7526 return ih;
7527
7528 return NULL;
7529 } /* get_input_handler */
7530
7531 /*-------------------------------------------------------------------------*/
7532 svalue_t *
7533 f_query_input_pending (svalue_t *sp)
7534
7535 /* EFUN query_input_pending()
7536 *
7537 * object query_input_pending(object ob)
7538 *
7539 * If ob is interactive and currently has an input_to() pending,
7540 * the object that has called the input_to() is returned,
7541 * else 0.
7542 */
7543
7544 {
7545 object_t *ob, *cb;
7546 interactive_t *ip;
7547
7548 ob = sp->u.ob;
7549 if (O_SET_INTERACTIVE(ip, ob) && ip->input_handler)
7550 {
7551 input_t *ih = ip->input_handler;
7552
7553 while (ih && ih->type != INPUT_TO)
7554 ih = ih->next;
7555
7556 if (ih)
7557 {
7558 cb = callback_object(&(((input_to_t*)ih)->fun));
7559 if (cb)
7560 sp->u.ob = ref_object(cb, "query_input_pending");
7561 else
7562 put_number(sp, 0);
7563 }
7564 else
7565 put_number(sp, 0);
7566 }
7567 else
7568 {
7569 put_number(sp, 0);
7570 }
7571
7572 deref_object(ob, "query_input_pending");
7573
7574 return sp;
7575 } /* f_query_input_pending() */
7576
7577 /*-------------------------------------------------------------------------*/
7578 svalue_t *
7579 v_find_input_to (svalue_t *sp, int num_arg)
7580
7581 /* EFUN: find_input_to()
7582 *
7583 * int find_input_to (object player, string|closure|object fun)
7584 * int find_input_to (object player, object ob, string fun)
7585 *
7586 * Find the input_to most recently added to the interactive <player> object
7587 * matching the <fun> argument:
7588 * - <fun> is a string: the input_to functionname has to match
7589 * - <fun> is an object: the object the input_to function is bound to has
7590 * to match
7591 * - <fun> is a closure: the input_to closure has to match.
7592 * If both <ob> and <fun> are specified, both the object and the function name
7593 * have to match.
7594 *
7595 * Return -1 if not found, or the position in the input_to stack (0 being
7596 * _least_ recently added input_to).
7597 */
7598
7599 {
7600 svalue_t *arg; /* Pointer to the arguments of the efun */
7601 int rc; /* Resultvalue */
7602
7603 arg = sp - num_arg + 1;
7604
7605 if (num_arg > 2)
7606 {
7607 if (arg[1].type == T_OBJECT && num_arg > 2 && arg[2].type != T_STRING)
7608 {
7609 vefun_bad_arg(3, sp);
7610 /* NOTREACHED */
7611 return NULL;
7612 }
7613
7614 if (arg[1].type != T_OBJECT
7615 )
7616 {
7617 vefun_bad_arg(2, sp);
7618 /* NOTREACHED */
7619 return NULL;
7620 }
7621 }
7622
7623 /* Process the command, terminating out when possible */
7624 do
7625 {
7626 input_t *ih;
7627 interactive_t *ip;
7628
7629 /* Get the interactive object.
7630 * If there is none, or if it is closing down or doesn't have
7631 * an input_to set, fail.
7632 */
7633 if (!(O_SET_INTERACTIVE(ip, arg[0].u.ob))
7634 || ip->closing || ip->input_handler == NULL
7635 )
7636 {
7637 rc = -1;
7638 break;
7639 }
7640
7641 /* Search for the right input_to */
7642
7643 for ( ih = ip->input_handler
7644 ; ih != NULL
7645 ; ih = ih->next)
7646 {
7647 input_to_t *it;
7648 Bool found = MY_FALSE;
7649
7650 if (ih->type != INPUT_TO)
7651 continue;
7652 it = (input_to_t*) ih;
7653
7654 switch (arg[1].type)
7655 {
7656 case T_STRING:
7657 if (!it->fun.is_lambda
7658 && mstreq(it->fun.function.named.name, arg[1].u.str))
7659 found = MY_TRUE;
7660 break;
7661
7662 case T_OBJECT:
7663 if (num_arg > 2)
7664 {
7665 if (callback_object(&(it->fun)) == arg[1].u.ob
7666 && !it->fun.is_lambda
7667 && it->fun.function.named.name == arg[2].u.str
7668 )
7669 found = MY_TRUE;
7670 }
7671 else
7672 {
7673 if (callback_object(&(it->fun)) == arg[1].u.ob)
7674 found = MY_TRUE;
7675 }
7676 break;
7677
7678 case T_CLOSURE:
7679 if (it->fun.is_lambda
7680 && closure_eq(&(it->fun.function.lambda), arg+1))
7681 found = MY_TRUE;
7682 break;
7683
7684 default:
7685 /* TODO: Wouldn't errorf() suffice? */
7686 fatal("Unsupported argument type %d\n", arg[1].type);
7687 break;
7688 }
7689
7690 if (found)
7691 break;
7692 }
7693
7694 if (ih != NULL)
7695 {
7696 /* We found the input_to: now count at which position it is */
7697 for ( rc = 0; ih->next != NULL; ih = ih->next)
7698 if (ih->type == INPUT_TO)
7699 rc++;
7700 break;
7701 }
7702
7703 /* At this point, we didn't find the input_to */
7704 rc = -1;
7705 } while (0);
7706
7707 /* Return the result */
7708 sp = pop_n_elems(num_arg, sp);
7709 sp++;
7710 put_number(sp, rc);
7711
7712 return sp;
7713 } /* f_find_input_to() */
7714
7715 /*-------------------------------------------------------------------------*/
7716 svalue_t *
7717 v_remove_input_to (svalue_t *sp, int num_arg)
7718
7719 /* EFUN: remove_input_to()
7720 *
7721 * int remove_input_to (object player)
7722 * int remove_input_to (object player, string|closure|object fun)
7723 * int remove_input_to (object player, object ob, string fun)
7724 *
7725 * Remove a pending input_to from the interactive <player> object.
7726 * If the optional <fun> is not given, the most recently added input_to
7727 * is removed.
7728 *
7729 * If the optional <fun> is given, the efun tries to find and remove the
7730 * most recently added input_to matching the <fun> argument:
7731 * - <fun> is a string: the input_to functionname has to match
7732 * - <fun> is an object: the object the input_to function is bound to has
7733 * to match
7734 * - <fun> is a closure: the input_to closure has to match.
7735 * If both <ob> and <fun> are specified, both the object and the function name
7736 * have to match.
7737 *
7738 * Return 1 on success, or 0 on failure (no input_to found, object is not
7739 * interactive or has no input_to pending).
7740 */
7741
7742 {
7743 svalue_t *arg; /* Pointer to the arguments of the efun */
7744 int rc; /* Resultvalue */
7745 interactive_t *ip;
7746 Bool removedFirst;
7747
7748 /* Get the arguments */
7749 arg = sp - num_arg + 1;
7750
7751 if (num_arg > 2)
7752 {
7753 if (arg[1].type == T_OBJECT && arg[2].type != T_STRING)
7754 {
7755 vefun_bad_arg(3, sp);
7756 /* NOTREACHED */
7757 return NULL;
7758 }
7759 if (arg[1].type != T_OBJECT)
7760 {
7761 vefun_bad_arg(2, sp);
7762 /* NOTREACHED */
7763 return NULL;
7764 }
7765 }
7766
7767
7768 /* Process the command, bailing out whenever necessary */
7769 do
7770 {
7771 input_t * prev;
7772 input_t *ih;
7773
7774 removedFirst = MY_FALSE;
7775
7776 /* Get the interactive object.
7777 * If there is none, or if it is closing down or doesn't have
7778 * an input_to set, fail.
7779 */
7780 if (!(O_SET_INTERACTIVE(ip, arg[0].u.ob))
7781 || ip->closing || ip->input_handler == NULL
7782 )
7783 {
7784 rc = 0;
7785 break;
7786 }
7787
7788 /* Search for the right input_to */
7789
7790 for (prev = NULL, ih = ip->input_handler
7791 ; ih != NULL
7792 ; prev = ih, ih = ih->next)
7793 {
7794 input_to_t *it;
7795 Bool found = MY_FALSE;
7796
7797 if (ih->type != INPUT_TO)
7798 continue;
7799 it = (input_to_t*) ih;
7800
7801 /* If no filter argument has been given, just remove
7802 * the first input to.
7803 */
7804 if (num_arg < 2)
7805 break;
7806
7807 switch (arg[1].type)
7808 {
7809 case T_STRING:
7810 if (!it->fun.is_lambda
7811 && mstreq(it->fun.function.named.name, arg[1].u.str))
7812 found = MY_TRUE;
7813 break;
7814
7815 case T_OBJECT:
7816 if (num_arg > 2)
7817 {
7818 if (callback_object(&(it->fun)) == arg[1].u.ob
7819 && !it->fun.is_lambda
7820 && it->fun.function.named.name == arg[2].u.str
7821 )
7822 found = MY_TRUE;
7823 }
7824 else
7825 {
7826 if (callback_object(&(it->fun)) == arg[1].u.ob)
7827 found = MY_TRUE;
7828 }
7829 break;
7830
7831 case T_CLOSURE:
7832 if (it->fun.is_lambda
7833 && closure_eq(&(it->fun.function.lambda), arg+1))
7834 found = MY_TRUE;
7835 break;
7836
7837 default:
7838 /* TODO: Wouldn't errorf() suffice? */
7839 fatal("Unsupported argument type %d\n", arg[1].type);
7840 break;
7841 }
7842
7843 if (found)
7844 break;
7845 }
7846
7847 if (ih != NULL)
7848 {
7849 /* We found the input_to: remove it */
7850 if (prev == NULL)
7851 {
7852 ip->input_handler = ih->next;
7853 removedFirst = MY_TRUE;
7854 }
7855 else
7856 prev->next = ih->next;
7857
7858 free_input_to((input_to_t*)ih);
7859 rc = 1;
7860 break;
7861 }
7862
7863 /* At this point, nothing worked: failure */
7864 rc = 0;
7865 } while (0);
7866
7867 if (rc && removedFirst)
7868 {
7869 if (ip->noecho)
7870 ip->noecho |= NOECHO_STALE;
7871 set_noecho(ip, ip->input_handler ? ip->input_handler->noecho : ip->noecho
7872 , ip->input_handler ? ip->input_handler->local : MY_FALSE
7873 , MY_FALSE
7874 );
7875 }
7876
7877 /* Return the result */
7878 sp = pop_n_elems(num_arg, sp);
7879 push_number(sp, rc);
7880
7881 return sp;
7882 } /* v_remove_input_to() */
7883
7884 /*-------------------------------------------------------------------------*/
7885 svalue_t *
7886 f_input_to_info (svalue_t *sp)
7887
7888 /* EFUN: input_to_info()
7889 *
7890 * mixed * input_to_info (object player)
7891 *
7892 * Construct an array of all input_to's pending for this interactive <player>.
7893 * The first entry in the array is the least recently added input_to, the
7894 * last element the most recently added one.
7895 * Every item in the array is itself an array of 2 or more entries:
7896 * 0: The object (only if the function is a string).
7897 * 1: The function (string or closure).
7898 * 2..: The argument(s).
7899 */
7900 {
7901 vector_t *v;
7902 int num_pending;
7903 input_t *ih;
7904 interactive_t *ip;
7905
7906 /* Get the interactive object.
7907 * If there is none, or if it is closing down or doesn't have
7908 * an input_to set, the efun will return the empty array.
7909 */
7910 if (!(O_SET_INTERACTIVE(ip, sp->u.ob))
7911 || ip->closing || ip->input_handler == NULL
7912 )
7913 {
7914 num_pending = 0;
7915 }
7916 else
7917 {
7918 /* Count the number of pending input_tos.
7919 */
7920 for ( num_pending = 0, ih = ip->input_handler
7921 ; ih != NULL
7922 ; ih = ih->next)
7923 if (ih->type == INPUT_TO)
7924 num_pending++;
7925 }
7926
7927 /* Allocate the result arrray and fill it in */
7928 v = allocate_array(num_pending);
7929
7930 if (num_pending > 0)
7931 {
7932 int i;
7933
7934 for (i = num_pending, ih = ip->input_handler
7935 ; --i >= 0
7936 ; ih = ih->next
7937 )
7938 {
7939 vector_t *vv;
7940 object_t *ob;
7941 input_to_t *it;
7942
7943 if (ih->type != INPUT_TO)
7944 {
7945 i++;
7946 continue;
7947 }
7948
7949 it = (input_to_t*) ih;
7950
7951 ob = callback_object(&(it->fun));
7952 if (!ob)
7953 continue;
7954
7955 /* Get the subarray */
7956
7957 vv = allocate_array(2 + it->fun.num_arg);
7958
7959 if (it->fun.is_lambda)
7960 {
7961 if (it->fun.function.lambda.x.closure_type == CLOSURE_LFUN)
7962 put_ref_object( vv->item
7963 , it->fun.function.lambda.u.lambda->function.lfun.ob
7964 , "input_to_info");
7965 else
7966 put_ref_object(vv->item, ob, "input_to_info");
7967 assign_svalue_no_free(&vv->item[1], &it->fun.function.lambda);
7968 }
7969 else
7970 {
7971 put_ref_object(vv->item, ob, "input_to_info");
7972 put_ref_string(vv->item + 1, it->fun.function.named.name);
7973 }
7974
7975 if (it->fun.num_arg > 0)
7976 {
7977 svalue_t *source, *dest;
7978 int nargs;
7979
7980 nargs = it->fun.num_arg;
7981 if (nargs > 1)
7982 source = it->fun.arg.u.lvalue;
7983 else
7984 source = &(it->fun.arg);
7985 dest = &vv->item[2];
7986 do {
7987 assign_svalue_no_free(dest++, source++);
7988 } while (--nargs);
7989 }
7990
7991 put_array(v->item + i, vv);
7992 }
7993 }
7994
7995 /* Return the result */
7996 free_svalue(sp);
7997 put_array(sp, v);
7998
7999 return sp;
8000 } /* f_input_to_info() */
8001
8002 /*-------------------------------------------------------------------------*/
8003 svalue_t *
8004 f_query_ip_name (svalue_t *sp)
8005
8006 /* EFUN query_ip_name()
8007 *
8008 * string query_ip_name(object ob)
8009 *
8010 * Give the ip-name for user the current user or for the optional
8011 * argument ob. An asynchronous process 'erq' is used to find
8012 * out these names in parallel. If there are any failures to find
8013 * the ip-name, then the ip-number is returned instead.
8014 */
8015
8016 {
8017 return query_ip_name(sp, MY_TRUE);
8018 } /* f_query_ip_name() */
8019
8020 /*-------------------------------------------------------------------------*/
8021 svalue_t *
8022 f_query_ip_number (svalue_t *sp)
8023
8024 /* EFUN query_ip_number()
8025 *
8026 * string query_ip_number(object ob)
8027 * string query_ip_number(mixed & ob)
8028 *
8029 * Give the ip-number for the current user or the optional
8030 * argument ob.
8031 *
8032 * If ob is given as reference (and it must be a valid object
8033 * then), it will upon return be set to the struct sockaddr_in of
8034 * the queried object, represented by an array of integers, one
8035 * integer per address byte:
8036 * ob[0.. 1]: sin_family
8037 * ob[2.. 3]: sin_port
8038 * ob[4.. 7]: sin_addr
8039 * ob[8..15]: undefined.
8040 */
8041
8042 {
8043 return query_ip_name(sp, MY_FALSE);
8044 } /* f_query_ip_number() */
8045
8046 /*-------------------------------------------------------------------------*/
8047 svalue_t *
8048 f_query_mud_port (svalue_t *sp)
8049
8050 /* EFUN: query_mud_port()
8051 *
8052 * Returns the port number the parser uses for user connections.
8053 *
8054 * int query_mud_port(void)
8055 *
8056 * If no argument is given, the port for this_player() is
8057 * returned. If this_player() is not existing or not interactive,
8058 * the first port number open for connections is returned.
8059 *
8060 * int query_mud_port(object user)
8061 * int query_mud_port(int num)
8062 *
8063 * If an user object is given, the port used for its connection
8064 * is returned.
8065 * If a positive number is given, the <num>th port number the
8066 * parser uses for connections is returned (given that there are
8067 * that many ports).
8068 * If -1 is given, the number of ports open for connections is
8069 * returned.
8070 */
8071
8072 {
8073 object_t *ob;
8074 interactive_t *ip;
8075 struct sockaddr_in addr;
8076 length_t length;
8077
8078 length = sizeof(addr);
8079
8080 if (sp->type == T_NUMBER)
8081 {
8082 if (sp->u.number < -1 || sp->u.number >= numports)
8083 {
8084 errorf("Bad arg 1 to query_mud_port(): value %"PRIdPINT" out of range.\n"
8085 , sp->u.number);
8086 /* NOTREACHED */
8087 }
8088 sp->u.number = sp->u.number < 0 ? numports : port_numbers[sp->u.number];
8089 return sp;
8090 }
8091
8092 ob = sp->u.ob;
8093 deref_object(ob, "query_ip_port");
8094
8095 if ( !(O_SET_INTERACTIVE(ip, ob))) {
8096 put_number(sp, port_numbers[0]);
8097 return sp;
8098 }
8099
8100 getsockname(ip->socket, (struct sockaddr *)&addr, &length);
8101 put_number(sp, ntohs(addr.sin_port));
8102 return sp;
8103 } /* f_query_mud_port() */
8104
8105 /*-------------------------------------------------------------------------*/
8106
8107
8108 static inline void translate_bit(char c, int i, int length, string_t *rc, unsigned int bitno)
8109 /* static helper function to translatin bits to characters in get_charset */
8110 {
8111 if (c & (1 << bitno))
8112 get_txt(rc)[length++] = (char)(i * 8 + bitno);
8113 } /* translate_bit */
8114
8115 static void
8116 get_charset (svalue_t * sp, p_int mode, char charset[32])
8117
8118 /* Translate the <charset> into an svalue and store it into <sp>:
8119 * <mode> == CHARSET_VECTOR: result is a bitvector array
8120 * <mode> == CHARSET_STRING: result is a string.
8121 */
8122
8123 {
8124 put_number(sp, 0);
8125 switch (mode)
8126 {
8127 default:
8128 fatal("(get_charset): Illegal mode value %"PRIdPINT"\n", mode);
8129 /* NOTREACHED */
8130 break;
8131
8132 case CHARSET_VECTOR:
8133 {
8134 vector_t * rc;
8135 int i;
8136
8137 rc = allocate_uninit_array(32);
8138 if (!rc)
8139 {
8140 outofmemory("result array");
8141 /* NOTREACHED */
8142 break;
8143 }
8144
8145 for (i = 0; i < 32; i++)
8146 put_number(rc->item+i, (unsigned char)charset[i]);
8147
8148 put_array(sp, rc);
8149 break;
8150 }
8151
8152 case CHARSET_STRING:
8153 {
8154 string_t * rc;
8155 int length, i;
8156
8157 /* Count the number of bits set in the charset */
8158 for (i = length = 0; i < 32; i++)
8159 {
8160 char c = charset[i];
8161 length += ((c & 0x80) ? 1 : 0)
8162 + ((c & 0x40) ? 1 : 0)
8163 + ((c & 0x20) ? 1 : 0)
8164 + ((c & 0x10) ? 1 : 0)
8165 + ((c & 0x08) ? 1 : 0)
8166 + ((c & 0x04) ? 1 : 0)
8167 + ((c & 0x02) ? 1 : 0)
8168 + ((c & 0x01) ? 1 : 0);
8169 }
8170
8171 rc = alloc_mstring(length);
8172 if (!rc)
8173 {
8174 outofmemory("result string");
8175 /* NOTREACHED */
8176 break;
8177 }
8178
8179 /* Translate the bits into characters */
8180 for (i = length = 0; i < 32; i++)
8181 {
8182 char c = charset[i];
8183
8184 translate_bit(c, i, length, rc, 0);
8185 translate_bit(c, i, length, rc, 1);
8186 translate_bit(c, i, length, rc, 2);
8187 translate_bit(c, i, length, rc, 3);
8188 translate_bit(c, i, length, rc, 4);
8189 translate_bit(c, i, length, rc, 5);
8190 translate_bit(c, i, length, rc, 6);
8191 translate_bit(c, i, length, rc, 7);
8192 }
8193
8194 put_string(sp, rc);
8195 break;
8196 } /* case CHARSET_STRING */
8197 } /* switch(mode) */
8198 } /* get_charset() */
8199
8200 /*-------------------------------------------------------------------------*/
8201 svalue_t *
8202 f_get_combine_charset (svalue_t *sp)
8203
8204 /* TEFUN: get_combine_charset()
8205 *
8206 * mixed get_combine_charset (int mode)
8207 *
8208 * Return the combine charset of the current interactive in the form requested
8209 * by <mode>:
8210 * <mode> == CHARSET_VECTOR: return as bitvector
8211 * <mode> == CHARSET_STRING: return as string
8212 *
8213 * The bitvector is interpreted as an array of 8-bit-values and might
8214 * contain up to 32 elements. Character n is "combinable"
8215 * if sizeof(bitvector) > n/8 && bitvector[n/8] & (1 << n%8) .
8216 *
8217 * If there is no current interactive, the function returns 0.
8218 */
8219
8220 {
8221 p_int mode;
8222 interactive_t *ip;
8223
8224 mode = sp->u.number;
8225 if (mode != CHARSET_VECTOR && mode != CHARSET_STRING)
8226 {
8227 errorf("Bad arg 1 to get_combine_charset(): %"PRIdPINT", "
8228 "expected CHARSET_VECTOR (%d) or CHARSET_STRING (%d)\n"
8229 , mode, CHARSET_VECTOR, CHARSET_STRING);
8230 /* NOTREACHED */
8231 return sp;
8232 }
8233
8234 if (current_interactive && O_SET_INTERACTIVE(ip, current_interactive))
8235 get_charset(sp, mode, ip->combine_cset);
8236 else
8237 put_number(sp, 0);
8238
8239 return sp;
8240 } /* f_get_combine_charset() */
8241
8242 /*-------------------------------------------------------------------------*/
8243 svalue_t *
8244 f_set_combine_charset (svalue_t *sp)
8245
8246 /* EFUN: set_combine_charset()
8247 *
8248 * void set_combine_charset (int* bitvector)
8249 * void set_combine_charset (string chars)
8250 * void set_combine_charset (0)
8251 *
8252 * Set the set of characters which can be combined into a single string
8253 * when received en-bloc in charmode from the current interactive user.
8254 * Non-combinable characters and single received characters are returned
8255 * in separate strings as usual. The function must be called with the
8256 * interactive user being the command giver.
8257 *
8258 * The newline '\n' and the NUL character '\0' are always non-combinable.
8259 *
8260 * The charset can be given either directly as a string, or indirectly
8261 * as a bitvector. If the charset is given as the number 0, the default
8262 * charset is re-established.
8263 *
8264 * The bitvector is interpreted as an array of 8-bit-values and might
8265 * contain up to 32 elements. Character n is "combinable"
8266 * if sizeof(bitvector) > n/8 && bitvector[n/8] & (1 << n%8) .
8267 */
8268
8269 {
8270 mp_int i;
8271 svalue_t *svp;
8272 char *p;
8273 interactive_t *ip;
8274
8275 i = 0;
8276 if (sp->type == T_POINTER && (i = (mp_int)VEC_SIZE(sp->u.vec)) > 32)
8277 {
8278 errorf("Bad arg 1 to set_combine_charset(): int[] too long (%"PRIdMPINT")\n"
8279 , i);
8280 /* NOTREACHED */
8281 return sp;
8282 }
8283
8284 if (current_interactive && O_SET_INTERACTIVE(ip, current_interactive))
8285 {
8286 if (sp->type == T_NUMBER)
8287 {
8288 set_default_combine_charset(ip->combine_cset);
8289 }
8290 else if (sp->type == T_STRING)
8291 {
8292 memset(ip->combine_cset, 0, sizeof ip->combine_cset);
8293 for ( i = mstrsize(sp->u.str), p = get_txt(sp->u.str)
8294 ; i > 0
8295 ; i--, p++)
8296 ip->combine_cset[(*p & 0xff) / 8] |= 1 << (*p % 8);
8297 }
8298 else
8299 {
8300 /* i was set in the typecheck above */
8301 for ( svp = sp->u.vec->item, p = ip->combine_cset
8302 ; --i >= 0
8303 ; svp++, p++)
8304 {
8305 if (svp->type == T_NUMBER)
8306 *p = (char)svp->u.number;
8307 }
8308 memset(p, 0, (size_t)(&ip->combine_cset[sizeof ip->combine_cset] - p));
8309 }
8310
8311 ip->combine_cset['\n'/8] &= ~(1 << '\n' % 8);
8312 ip->combine_cset['\0'/8] &= ~(1 << '\0' % 8);
8313 }
8314 free_svalue(sp);
8315 sp--;
8316 return sp;
8317 } /* f_set_combine_charset() */
8318
8319 /*-------------------------------------------------------------------------*/
8320 svalue_t *
8321 f_get_connection_charset (svalue_t *sp)
8322
8323 /* TEFUN: get_connection_charset()
8324 *
8325 * mixed get_connection_charset (int mode)
8326 *
8327 * Return the combine charset of the current interactive in the form requested
8328 * by <mode>:
8329 * <mode> == CHARSET_VECTOR: return as bitvector
8330 * <mode> == CHARSET_STRING: return as string
8331 *
8332 * Alternatively, the status of the IAC quoting can be returned:
8333 * <mode> == CHARSET_QUOTE_IAC: return 0 if IACs are not quoted,
8334 * return 1 if they are.
8335 *
8336 * The bitvector is interpreted as an array of 8-bit-values and might
8337 * contain up to 32 elements. Character n is "combinable"
8338 * if sizeof(bitvector) > n/8 && bitvector[n/8] & (1 << n%8) .
8339 *
8340 * If there is no current interactive, the function returns 0.
8341 */
8342
8343 {
8344 p_int mode;
8345 interactive_t *ip;
8346
8347 mode = sp->u.number;
8348 if (mode != CHARSET_VECTOR && mode != CHARSET_STRING
8349 && mode != CHARSET_QUOTE_IAC)
8350 {
8351 errorf("Bad arg 1 to get_connection_charset(): %"PRIdPINT", "
8352 "expected CHARSET_VECTOR (%d), _STRING (%d), "
8353 "or _QUOTE_IAC (%d)\n"
8354 , mode, CHARSET_VECTOR, CHARSET_STRING, CHARSET_QUOTE_IAC);
8355 /* NOTREACHED */
8356 return sp;
8357 }
8358
8359 if (current_interactive && O_SET_INTERACTIVE(ip, current_interactive))
8360 {
8361 if (mode == CHARSET_QUOTE_IAC)
8362 put_number(sp, ip->quote_iac != 0);
8363 else
8364 get_charset(sp, mode, ip->charset);
8365 }
8366 else
8367 put_number(sp, 0);
8368
8369 return sp;
8370 } /* f_get_connection_charset() */
8371
8372 /*-------------------------------------------------------------------------*/
8373 svalue_t *
8374 f_set_connection_charset (svalue_t *sp)
8375
8376 /* EFUN: set_connection_charset()
8377 *
8378 * void set_connection_charset (int* bitvector, int quote_iac)
8379 * void set_connection_charset (string charset, int quote_iac)
8380 * void set_connection_charset (0, int quote_iac)
8381 *
8382 * Set the set of characters that can be output to the interactive user
8383 * (this does not apply to binary_message() ). The function must be called
8384 * by the interactive user object itself.
8385 *
8386 * The charset can be given either directly as a string, or indirectly
8387 * as a bitvector. If the charset is given as 0, the default connection
8388 * charset is re-established.
8389 *
8390 * The bitvector is interpreted as an array of 8-bit-values and might
8391 * contain up to 32 elements. Character n is allowed to be output
8392 * if sizeof(bitvector) > n/8 && bitvector[n/8] & (1 << n%8) .
8393 *
8394 * If quote_iac is 0 and char 255 is allowed to be output, IAC
8395 * will be output unmodified.
8396 * If quote_iac is 1 and char 255 is allowed to be output,
8397 * char 255 will be quoted so that it is not interpreted as IAC
8398 * by the telnet protocol.
8399 */
8400
8401 {
8402 mp_int i;
8403 svalue_t *svp;
8404 char *p;
8405 interactive_t *ip;
8406
8407 i = 0;
8408 if (sp[-1].type == T_POINTER && (i = (mp_int)VEC_SIZE(sp[-1].u.vec)) > 32)
8409 {
8410 errorf("Bad arg 1 to set_connection_charset(): array too big (%"
8411 PRIdMPINT")\n", i);
8412 /* NOTREACHED */
8413 return sp;
8414 }
8415
8416 if (O_SET_INTERACTIVE(ip, current_object))
8417 {
8418 if (sp[-1].type == T_NUMBER)
8419 {
8420 set_default_conn_charset(ip->charset);
8421 }
8422 else if (sp[-1].type == T_STRING)
8423 {
8424 memset(ip->charset, 0, sizeof ip->charset);
8425 for ( i = mstrsize((sp-1)->u.str), p = get_txt(sp[-1].u.str)
8426 ; i > 0
8427 ; i--, p++)
8428 ip->charset[(*p & 0xff) / 8] |= 1 << (*p % 8);
8429 }
8430 else
8431 {
8432 /* i was set in the typecheck above */
8433 for ( svp = sp[-1].u.vec->item, p = ip->charset
8434 ; --i >= 0
8435 ; svp++, p++)
8436 {
8437 if (svp->type == T_NUMBER)
8438 *p = (char)svp->u.number;
8439 }
8440 memset(p, 0, (size_t)(&ip->charset[sizeof ip->charset] - p));
8441 }
8442
8443 ip->quote_iac = (char)sp->u.number;
8444 }
8445 sp--;
8446 free_svalue(sp);
8447 sp--;
8448 return sp;
8449 } /* f_set_connection_charset() */
8450
8451 /*-------------------------------------------------------------------------*/
8452 svalue_t *
8453 f_set_prompt (svalue_t *sp)
8454
8455 /* EFUN set_prompt()
8456 *
8457 * string set_prompt(mixed prompt, object ob)
8458 *
8459 * Set the prompt given by the first argument for the interactive object
8460 * instead of the default ``> ''. If the second argument is omitted,
8461 * this_player() is used as default. The first arg can be a string or a
8462 * closure. If the <prompt> arg is 0, the prompt is not changed.
8463 * TODO: Remove the acceptance of -1 here.
8464 *
8465 * The result returned is the old prompt.
8466 */
8467
8468 {
8469 svalue_t *prompt;
8470 interactive_t *ip;
8471
8472 /* Make sure the object is interactive */
8473 if (!(O_SET_INTERACTIVE(ip, sp->u.ob))
8474 || ip->closing)
8475 {
8476 errorf("Bad arg 2 to set_prompt(): object not interactive.\n");
8477 return sp;
8478 }
8479
8480 /* Get the address of the prompt svalue */
8481 prompt = &O_GET_INTERACTIVE(sp->u.ob)->prompt;
8482
8483 free_object_svalue(sp);
8484 sp--;
8485
8486 if (sp->type == T_STRING || sp->type == T_CLOSURE)
8487 {
8488 if (sp->type == T_CLOSURE && sp->x.closure_type == CLOSURE_UNBOUND_LAMBDA)
8489 {
8490 inter_sp = sp;
8491 errorf("Bad arg 1 for set_prompt(): lambda closure not bound\n");
8492 /* NOTREACHED */
8493 }
8494
8495 if (sp->type == T_STRING)
8496 {
8497 string_t *str = make_tabled_from(sp->u.str);
8498
8499 if (!str)
8500 {
8501 inter_sp = sp;
8502 errorf("(set_prompt) Out of memory (%zu bytes) for prompt\n"
8503 , mstrsize(sp->u.str));
8504 }
8505 else
8506 {
8507 free_mstring(sp->u.str);
8508 sp->u.str = str;
8509 }
8510 }
8511
8512 /* Three-way exchange to set the new prompt and put
8513 * the old one onto the stack.
8514 */
8515 sp[1] = *prompt;
8516 *prompt = *sp;
8517 *sp = sp[1];
8518 }
8519 else /* It's a number */
8520 {
8521 if (sp->u.number == 0 || sp->u.number == -1)
8522 assign_svalue(sp, prompt);
8523 else
8524 {
8525 errorf("Bad int arg 1 to set_prompt(): got %"PRIdPINT", expected 0 or -1.\n"
8526 , sp->u.number);
8527 /* NOTREACHED */
8528 return sp;
8529 }
8530 }
8531
8532 return sp;
8533 } /* f_set_prompt() */
8534
8535 /*-------------------------------------------------------------------------*/
8536 svalue_t *
8537 v_snoop (svalue_t *sp, int num_arg)
8538
8539 /* EFUN snoop()
8540 *
8541 * object snoop(object snooper)
8542 * object snoop(object snooper, object snoopee)
8543 *
8544 * Starts a snoop from 'snooper' on 'snoopee', or if 'snoopee' is not
8545 * given, terminates any snoop from 'snooper'.
8546 * On success, 'snoopee' is returned, else 0.
8547 *
8548 * The snoop is checked with the master object for validity.
8549 * It will also fail if the 'snoopee' is being snooped already or
8550 * if a snoop would result in a recursive snoop action.
8551 */
8552
8553 {
8554 int i;
8555
8556 if (num_arg == 1)
8557 {
8558 i = set_snoop(sp->u.ob, 0);
8559 }
8560 else
8561 {
8562 i = set_snoop((sp-1)->u.ob, sp->u.ob);
8563 free_svalue(sp--);
8564 }
8565 free_svalue(sp);
8566 put_number(sp, i);
8567
8568 return sp;
8569 } /* v_snoop() */
8570
8571 /*-------------------------------------------------------------------------*/
8572 svalue_t *
8573 f_users (svalue_t *sp)
8574
8575 /* EFUN users()
8576 *
8577 * Return a (possibly empty) vector of all interactive user objects.
8578 */
8579
8580 {
8581 object_t *ob;
8582 int n, num;
8583 vector_t *ret;
8584 interactive_t **user;
8585 svalue_t *svp;
8586
8587 /* Count the active users */
8588 num = 0;
8589 user = all_players;
8590 for (n = max_player + 2; --n; user++)
8591 {
8592 if (*user && !((*user)->ob->flags & O_DESTRUCTED))
8593 num++;
8594 }
8595
8596 /* Get the result array and fill it */
8597
8598 ret = allocate_array(num);
8599 svp = ret->item;
8600 user = all_players;
8601 for (n = max_player + 2; --n; user++)
8602 {
8603 if (*user && !((ob = (*user)->ob)->flags & O_DESTRUCTED))
8604 {
8605 put_ref_object(svp, ob, "users");
8606 svp++;
8607 }
8608 }
8609
8610 push_array(sp, ret);
8611
8612 return sp;
8613 } /* f_users() */
8614
8615 /*-------------------------------------------------------------------------*/
8616 svalue_t *
8617 f_query_udp_port (svalue_t *sp)
8618
8619 /* EFUN query_udp_port()
8620 *
8621 * int query_udp_port(void)
8622 *
8623 * Returns the port number that is used for the inter mud
8624 * protocol.
8625 */
8626
8627 {
8628 push_number(sp, udp_port);
8629
8630 return sp;
8631 } /* f_query_udp_port() */
8632
8633 /*-------------------------------------------------------------------------*/
8634 svalue_t *
8635 f_get_max_commands (svalue_t *sp)
8636
8637 /* TEFUN: get_max_commands()
8638 *
8639 * int get_max_commands ()
8640 * int get_max_commands (object obj)
8641 *
8642 * Return the max number of commands (read: line resp. char inputs) the
8643 * interactive <obj> (default is the current interactive) is allowed to
8644 * execute per second. A negative result means 'unlimited'.
8645 * For non-interactive objects the result is 0.
8646 */
8647
8648 {
8649 p_int rc;
8650 interactive_t *ip;
8651
8652 rc = 0;
8653 if (O_SET_INTERACTIVE(ip, sp->u.ob))
8654 rc = ip->maxNumCmds;
8655
8656 free_svalue(sp);
8657 put_number(sp, rc);
8658
8659 return sp;
8660 } /* f_get_max_commands() */
8661
8662 /*-------------------------------------------------------------------------*/
8663 svalue_t *
8664 f_set_max_commands (svalue_t *sp)
8665
8666 /* TEFUN: set_max_commands()
8667 *
8668 * void set_max_commands (int num)
8669 * void set_max_commands (int num, object obj)
8670 *
8671 * Set the max number of commands (read: line resp. char inputs) the
8672 * interactive <obj> (default is the current interactive) is allowed to
8673 * execute per second to <num>. A negative result means 'unlimited'.
8674 * For non-interactive objects the function raises an error.
8675 *
8676 * The function raises a privilege_violation ("set_max_commands", obj, num).
8677 * If the privilege is denied, the call is ignored.
8678 */
8679
8680 {
8681 p_int num;
8682 interactive_t *ip;
8683
8684 num = sp[-1].u.number;
8685 if (num < 0)
8686 num = -1;
8687
8688 if (!O_SET_INTERACTIVE(ip, sp->u.ob))
8689 {
8690 errorf("Bad arg 2 to set_max_commands(): Object is not interactive.\n");
8691 /* NOTREACHED */
8692 }
8693
8694 if (privilege_violation4(STR_SET_MAX_CMDS, sp->u.ob, NULL, num, sp))
8695 ip->maxNumCmds = num;
8696
8697 free_svalue(sp--);
8698 free_svalue(sp--);
8699 return sp;
8700 } /* f_set_max_commands() */
8701
8702 /*-------------------------------------------------------------------------*/
8703 svalue_t *
8704 f_enable_telnet (svalue_t *sp)
8705
8706 /* TEFUN: enable_telnet()
8707 *
8708 * int enable_telnet (int num)
8709 * int enable_telnet (int num, object obj)
8710 *
8711 * Enable or disable the telnet machine for the interactive object <obj>.
8712 * Return the previous state of the telnet machine as result.
8713 *
8714 * <num> > 0 : enable telnet machine (default)
8715 * = 0 : disable telnet machine
8716 * < 0 : just query the current state of the telnet machine.
8717 * <obj> : the interactive object, default is the current interactive.
8718 * For non-interactive objects the function raises an error.
8719 *
8720 * The function raises a privilege_violation ("enable_telnet", obj, num)
8721 * if <num> is >= 0. If the privilege is denied, the call is ignored.
8722 *
8723 * WARNING: Careless use of this efun can cause great confusion for both
8724 * driver and clients!
8725 */
8726
8727 {
8728 p_int num;
8729 p_int rc;
8730 interactive_t *ip;
8731
8732 num = sp[-1].u.number;
8733 if (num < 0)
8734 num = -1;
8735
8736 if (!O_SET_INTERACTIVE(ip, sp->u.ob))
8737 {
8738 errorf("Bad arg 2 to enable_telnet(): Object '%s' is not interactive.\n"
8739 , get_txt(sp->u.ob->name)
8740 );
8741 /* NOTREACHED */
8742 return sp; /* flow control hint */
8743 }
8744
8745 rc = (ip->tn_enabled != 0);
8746 if (num >= 0
8747 && privilege_violation4(STR_ENABLE_TELNET, sp->u.ob, NULL, num, sp))
8748 ip->tn_enabled = (num != 0);
8749
8750 free_svalue(sp--);
8751 free_svalue(sp);
8752
8753 put_number(sp, rc);
8754 return sp;
8755 } /* f_enable_telnet() */
8756
8757 /*-------------------------------------------------------------------------*/
8758 void
8759 check_for_out_connections (void)
8760
8761 /* Check the list of pending outgoing connections if the connections
8762 * are still pending.
8763 * Activate those who succeeded, remove those which failed.
8764 *
8765 * To be called regularily from the backend.
8766 */
8767
8768 {
8769 int i, ret;
8770 object_t *user;
8771
8772 for (i = 0; i < MAX_OUTCONN; i++)
8773 {
8774 if (outconn[i].status == ocNotUsed)
8775 continue;
8776
8777 if (!outconn[i].curr_obj) /* shouldn't happen */
8778 {
8779 socket_close(outconn[i].socket);
8780 outconn[i].status = ocNotUsed;
8781 continue;
8782 }
8783
8784 if (outconn[i].status == ocLoggingOn)
8785 {
8786 /* LPC logon threw an error - clean up */
8787 debug_message("%s Error in net_connect(): logon "
8788 "object '%s' threw an error.\n"
8789 , time_stamp()
8790 , outconn[i].curr_obj
8791 ? get_txt(outconn[i].curr_obj->name)
8792 : "<null>"
8793 );
8794
8795 outconn[i].status = ocNotUsed;
8796 if (outconn[i].curr_obj)
8797 {
8798 if (O_IS_INTERACTIVE(outconn[i].curr_obj))
8799 remove_interactive(outconn[i].curr_obj, MY_FALSE);
8800 free_object(outconn[i].curr_obj, "net_connect");
8801 }
8802 socket_close(outconn[i].socket);
8803 continue;
8804 }
8805
8806 if (outconn[i].curr_obj && (outconn[i].curr_obj->flags & O_DESTRUCTED))
8807 {
8808 socket_close(outconn[i].socket);
8809 free_object(outconn[i].curr_obj, "net_connect");
8810 outconn[i].status = ocNotUsed;
8811 continue;
8812 }
8813
8814 ret = connect(outconn[i].socket, (struct sockaddr*) &outconn[i].target
8815 , sizeof(outconn[i].target));
8816 if (ret == -1)
8817 {
8818 switch(errno)
8819 {
8820 case EALREADY: /* still trying */
8821 continue;
8822 case EISCONN: /* we are connected! */
8823 break;
8824 default:
8825 /* Error with connection, call logon() with the failure flag
8826 */
8827 outconn[i].status = ocLoggingOn;
8828 push_number(inter_sp, -1);
8829 logon_object(outconn[i].curr_obj);
8830
8831 outconn[i].status = ocNotUsed;
8832 free_object(outconn[i].curr_obj, "net_connect");
8833 socket_close(outconn[i].socket);
8834
8835 continue;
8836 }
8837 }
8838
8839 /* connection successful */
8840 outconn[i].status = ocLoggingOn;
8841
8842 user = command_giver;
8843 new_player( outconn[i].curr_obj, outconn[i].socket
8844 , &outconn[i].target, sizeof(outconn[i].target), 0);
8845 command_giver = user;
8846
8847 free_object(outconn[i].curr_obj, "net_connect");
8848 outconn[i].status = ocNotUsed;
8849 }
8850 } /* check_for_out_connections() */
8851
8852 /*-------------------------------------------------------------------------*/
8853 svalue_t *
8854 f_net_connect (svalue_t *sp)
8855
8856 /* EFUN net_connect()
8857 *
8858 * int net_connect(string host, int port)
8859 *
8860 * Open a non-blocking TCP network connection to <host> and <port>.
8861 * On success, the connection is bound to the current object and the
8862 * lfun logon() is called in the object.
8863 *
8864 * If the connection can't be established immediately, the efun returns
8865 * 'success' and the driver will check in the background for the progress
8866 * of the connection. When it is established, logon() will be called in
8867 * the object. If the connection fails, logon(-1) will be called in the
8868 * object.
8869 *
8870 * The efun raises a privilege violation ("net_connect", host, port).
8871 *
8872 * Return 0 on success, and a Unix ERRNO on failure.
8873 */
8874
8875 {
8876 char * host;
8877 int port;
8878 int rc;
8879
8880 /* get the arguments */
8881
8882 host = get_txt(sp[-1].u.str);
8883 port = sp->u.number;
8884
8885 if (!privilege_violation4(STR_NET_CONNECT, NULL, sp[-1].u.str, port, sp))
8886 {
8887 sp = pop_n_elems(2, sp);
8888 push_number(sp, -1);
8889 return sp;
8890 }
8891
8892 /* Try the connection */
8893 rc = 0;
8894 do{
8895 int d, n, ret;
8896 object_t *user;
8897 struct sockaddr_in target;
8898
8899 #ifndef USE_IPV6
8900
8901 struct hostent *h;
8902
8903 #endif
8904
8905 /* Find a place to store the pending connection,
8906 * store the index in n
8907 */
8908 Bool stored = MY_FALSE;
8909 for (n = 0; n < MAX_OUTCONN; n++)
8910 {
8911 if (outconn[n].status == ocNotUsed)
8912 {
8913 stored = MY_TRUE;
8914 break;
8915 }
8916 }
8917
8918 if (!stored)
8919 {
8920 rc = EMFILE;
8921 break;
8922 }
8923
8924 #ifndef USE_IPV6
8925
8926 /* Attempt the connection */
8927
8928 target.sin_port = htons(port);
8929 /* TODO: Uh-oh, blocking DNS in the execution thread.
8930 * TODO:: Better would be to start an ERQ lookup and fill in the
8931 * TODO:: data in the background.
8932 */
8933 h = gethostbyname(host);
8934 target.sin_addr.s_addr = h ? ** (uint32 **) (h -> h_addr_list)
8935 : inet_addr(host);
8936 if (!target.sin_addr.s_addr)
8937 {
8938 rc = -1;
8939 break;
8940 }
8941
8942 target.sin_family = h ? h -> h_addrtype : AF_INET;
8943 d = socket (target.sin_family, SOCK_STREAM, 0);
8944 if (d == -1) {
8945 perror ("socket");
8946 rc = errno;
8947 break;
8948 }
8949
8950 set_socket_nonblocking(d);
8951
8952 /* On multihomed machines it is important to bind the socket to
8953 * the proper IP address.
8954 */
8955 ret = bind(d, (struct sockaddr *) &host_ip_addr_template, sizeof(host_ip_addr_template));
8956 if (ret == -1) {
8957 perror("bind during net_connect");
8958 rc = errno;
8959 break;
8960 }
8961
8962 ret = connect(d, (struct sockaddr *) &target, sizeof(target));
8963 #else
8964 d = ret = open_ipv6_conn(host, port, &target);
8965 #endif
8966 if (ret == -1 && errno != EINPROGRESS)
8967 {
8968 /* error with connection */
8969 perror("net_connect");
8970 socket_close(d);
8971 rc = errno;
8972 break;
8973 }
8974
8975 rc = 0;
8976
8977 /* Store the connection in the outconn[] table even if
8978 * we can complete it immediately. For the reason see below.
8979 */
8980 outconn[n].socket = d;
8981 outconn[n].target = target;
8982 outconn[n].curr_obj = ref_object(current_object, "net_conect");
8983
8984 if (errno == EINPROGRESS)
8985 {
8986 /* Can't complete right now */
8987 outconn[n].status = ocUsed;
8988 break;
8989 }
8990
8991 /* Attempt the logon. By setting the outconn[].status to
8992 * ocLoggingOn, any subsequent call to check_for_out_connections()
8993 * will clean up for us.
8994 */
8995 outconn[n].status = ocLoggingOn;
8996
8997 user = command_giver;
8998 inter_sp = sp;
8999 new_player(current_object, d, &target, sizeof(target), 0);
9000 command_giver = user;
9001
9002 /* All done - clean up */
9003 outconn[n].status = ocNotUsed;
9004 free_object(outconn[n].curr_obj, "net_connect");
9005 }while(0);
9006
9007 /* Return the result */
9008 sp = pop_n_elems(2, sp);
9009 push_number(sp, rc);
9010
9011 return sp;
9012 } /* f_net_connect() */
9013
9014 /*-------------------------------------------------------------------------*/
9015 svalue_t *
9016 f_configure_interactive (svalue_t *sp)
9017
9018 /* EFUN configure_interactive()
9019 *
9020 * void configure_interactive(object ob, int what, mixed data)
9021 *
9022 * Sets the option <what> to the value <data> on the interactive <ob>
9023 * or the default for all interactives if <ob> is 0.
9024 *
9025 * <what> == IC_MAX_WRITE_BUFFER_SIZE
9026 *
9027 * If the first argument <ob> is not this_object(), the privilege violation
9028 * ("configure_interactive", this_object(), ob, what, data) occurs.
9029 */
9030
9031 {
9032 object_t *ob;
9033 interactive_t *ip;
9034
9035 if (sp[-2].type == T_OBJECT)
9036 {
9037 ob = sp[-2].u.ob;
9038
9039 if (!O_SET_INTERACTIVE(ip, ob))
9040 {
9041 errorf("Bad arg 1 to configure_interactive(): "
9042 "Object '%s' is not interactive.\n"
9043 , get_txt(ob->name)
9044 );
9045 return sp; /* NOTREACHED */
9046 }
9047 }
9048 else
9049 {
9050 ob = NULL;
9051 ip = NULL;
9052 }
9053
9054 if (ob != current_object
9055 && !privilege_violation_n(STR_CONFIGURE_INTERACTIVE, ob, sp, 2))
9056 {
9057 sp = pop_n_elems(3, sp);
9058 return sp;
9059 }
9060
9061 switch(sp[-1].u.number)
9062 {
9063 default:
9064 errorf("Illegal value %"PRIdPINT" for configure_interactive().\n", sp[-1].u.number);
9065 return sp; /* NOTREACHED */
9066
9067 case IC_MAX_WRITE_BUFFER_SIZE:
9068 {
9069 int max;
9070
9071 if (sp->type != T_NUMBER)
9072 efun_exp_arg_error(3, TF_NUMBER, sp->type, sp);
9073
9074 max = sp->u.number;
9075 if (max < 0)
9076 max = -1;
9077
9078 if (!ip)
9079 write_buffer_max_size = max;
9080 else
9081 ip->write_max_size = max;
9082 break;
9083 }
9084 }
9085
9086 sp = pop_n_elems(3, sp);
9087 return sp;
9088 } /* f_configure_interactive() */
9089
9090 /***************************************************************************/
9091