sbbs.h 52 KB
Newer Older
1
2
3
4
5
6
/* Synchronet class (sbbs_t) definition and exported function prototypes */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#ifndef _SBBS_H
#define _SBBS_H

/****************************/
/* Standard library headers */
/****************************/

rswindell's avatar
rswindell committed
29
30
31
/***************/
/* OS-specific */
/***************/
32
#if defined(_WIN32)			/* Windows */
33

deuce's avatar
deuce committed
34
35
36
	#define NOCRYPT     /* Stop windows.h from loading wincrypt.h */
                    /* Is windows.h REALLY necessary?!?! */
	#define WIN32_LEAN_AND_MEAN
37
38
39
40
41
42
	#include <io.h>
	#include <share.h>
	#include <windows.h>
	#include <process.h>	/* _beginthread() prototype */
	#include <direct.h>		/* _mkdir() prototype */
	#include <mmsystem.h>	/* SND_ASYNC */
43

44
	#if defined(_DEBUG) && defined(_MSC_VER)
45
46
47
		#include <crtdbg.h> /* Windows debug macros and stuff */
	#endif

48
#if defined(__cplusplus)
49
	extern "C"
50
#endif
deuce's avatar
deuce committed
51
	HINSTANCE hK32;
52

53
#elif defined(__unix__)		/* Unix-variant */
54

55
	#include <unistd.h>		/* close */
56
57
58

#endif

59
60
61
62
63
64
#ifdef _THREAD_SUID_BROKEN
extern int	thread_suid_broken;			/* NPTL is no longer broken */
#else
#define thread_suid_broken FALSE
#endif

rswindell's avatar
rswindell committed
65
66
67
/******************/
/* ANSI C Library */
/******************/
68
69
70
71
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
72
#include <fcntl.h>			/* open */
73
74
75
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
76

77
#ifndef __unix__
78
79
80
81
82

	#include <malloc.h>

#endif

83
84
#include <sys/stat.h>

deuce's avatar
deuce committed
85
86
87
88
89
90
#ifdef __unix__
	#define XP_UNIX
#else
	#define XP_PC
	#define XP_WIN
#endif
rswindell's avatar
rswindell committed
91
92
93

#if defined(JAVASCRIPT)
#include "comio.h"			/* needed for COM_HANDLE definition only */
94
#if __GNUC__ > 5
rswindell's avatar
rswindell committed
95
96
97
98
	#pragma GCC diagnostic push
	#pragma GCC diagnostic ignored "-Wmisleading-indentation"
	#pragma GCC diagnostic ignored "-Wignored-attributes"
#endif
deuce's avatar
deuce committed
99
100
#include <jsversion.h>
#include <jsapi.h>
101
#if __GNUC_ > 5
rswindell's avatar
rswindell committed
102
103
	#pragma GCC diagnostic pop
#endif
deuce's avatar
deuce committed
104
#define JS_DestroyScript(cx,script)
105

106
107
#define JSSTRING_TO_RASTRING(cx, str, ret, sizeptr, lenptr) \
{ \
108
	size_t			*JSSTSlenptr=(lenptr); \
109
110
111
112
113
114
115
116
117
	size_t			JSSTSlen; \
	size_t			JSSTSpos; \
	const jschar	*JSSTSstrval; \
	char			*JSSTStmpptr; \
\
	if(JSSTSlenptr==NULL) \
		JSSTSlenptr=&JSSTSlen; \
	if((str) != NULL) { \
		if((JSSTSstrval=JS_GetStringCharsAndLength((cx), (str), JSSTSlenptr))) { \
118
119
120
			if((*(sizeptr) < (*JSSTSlenptr+1 )) || (ret)==NULL) { \
				*(sizeptr) = *JSSTSlenptr+1; \
				if((JSSTStmpptr=(char *)realloc((ret), *(sizeptr)))==NULL) { \
121
					JS_ReportError(cx, "Error reallocating %lu bytes at %s:%d", (*JSSTSlenptr)+1, getfname(__FILE__), __LINE__); \
122
					if((ret) != NULL) free(ret); \
123
124
125
126
127
128
129
130
131
132
133
134
135
					(ret)=NULL; \
				} \
				else { \
					(ret)=JSSTStmpptr; \
				} \
			} \
			if(ret) { \
				for(JSSTSpos=0; JSSTSpos<*JSSTSlenptr; JSSTSpos++) \
					(ret)[JSSTSpos]=(char)JSSTSstrval[JSSTSpos]; \
				(ret)[*JSSTSlenptr]=0; \
			} \
		} \
	} \
deuce's avatar
deuce committed
136
137
	else { \
		if(ret) \
138
			*(ret)=0; \
deuce's avatar
deuce committed
139
	} \
140
141
142
143
144
145
146
147
}

#define JSVALUE_TO_RASTRING(cx, val, ret, sizeptr, lenptr) \
{ \
	JSString	*JSVTSstr=JS_ValueToString((cx), (val)); \
	JSSTRING_TO_RASTRING((cx), JSVTSstr, (ret), (sizeptr), (lenptr)); \
}

148
149
#define JSSTRING_TO_MSTRING(cx, str, ret, lenptr) \
{ \
150
	size_t			*JSSTSlenptr=(lenptr); \
151
152
153
154
155
156
157
158
159
160
161
162
163
164
	size_t			JSSTSlen; \
	size_t			JSSTSpos; \
	const jschar	*JSSTSstrval; \
\
	if(JSSTSlenptr==NULL) \
		JSSTSlenptr=&JSSTSlen; \
	(ret)=NULL; \
	if((str) != NULL) { \
		if((JSSTSstrval=JS_GetStringCharsAndLength((cx), (str), JSSTSlenptr))) { \
			if(((ret)=(char *)malloc(*JSSTSlenptr+1))) { \
				for(JSSTSpos=0; JSSTSpos<*JSSTSlenptr; JSSTSpos++) \
					(ret)[JSSTSpos]=(char)JSSTSstrval[JSSTSpos]; \
				(ret)[*JSSTSlenptr]=0; \
			} \
165
			else JS_ReportError((cx), "Error allocating %lu bytes at %s:%d", (*JSSTSlenptr)+1, getfname(__FILE__), __LINE__); \
166
167
168
169
170
171
172
173
174
175
		} \
	} \
}

#define JSVALUE_TO_MSTRING(cx, val, ret, lenptr) \
{ \
	JSString	*JSVTSstr=JS_ValueToString((cx), (val)); \
	JSSTRING_TO_MSTRING((cx), JSVTSstr, (ret), lenptr); \
}

176
177
#define JSSTRING_TO_STRBUF(cx, str, ret, bufsize, lenptr) \
{ \
178
	size_t			*JSSTSlenptr=(lenptr); \
179
180
181
182
183
184
	size_t			JSSTSlen; \
	size_t			JSSTSpos; \
	const jschar	*JSSTSstrval; \
\
	if(JSSTSlenptr==NULL) \
		JSSTSlenptr=&JSSTSlen; \
185
	if((bufsize) < 1 || (str)==NULL) \
186
187
188
		*JSSTSlenptr = 0; \
	else { \
		if((JSSTSstrval=JS_GetStringCharsAndLength((cx), (str), JSSTSlenptr))) { \
189
190
			if(*JSSTSlenptr >= (bufsize)) \
				*JSSTSlenptr = (bufsize)-1; \
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
			for(JSSTSpos=0; JSSTSpos<*JSSTSlenptr; JSSTSpos++) \
				(ret)[JSSTSpos]=(char)JSSTSstrval[JSSTSpos]; \
		} \
		else \
			*JSSTSlenptr=0; \
	} \
	(ret)[*JSSTSlenptr]=0; \
}

#define JSVALUE_TO_STRBUF(cx, val, ret, bufsize, lenptr) \
{ \
	JSString	*JSVTSstr=JS_ValueToString((cx), (val)); \
	JSSTRING_TO_STRBUF((cx), JSVTSstr, (ret), (bufsize), lenptr); \
}

206
207
208
209
210
211
#define HANDLE_PENDING(cx, p ) \
	if(JS_IsExceptionPending(cx)) { \
		if(p != NULL) \
			free(p); \
		return JS_FALSE; \
	}
212

213
214
#define JSSTRING_TO_ASTRING(cx, str, ret, maxsize, lenptr) \
{ \
215
	size_t			*JSSTSlenptr=(lenptr); \
216
217
218
219
220
221
222
223
224
	size_t			JSSTSlen; \
	size_t			JSSTSpos; \
	const jschar	*JSSTSstrval; \
\
	if(JSSTSlenptr==NULL) \
		JSSTSlenptr=&JSSTSlen; \
	(ret)=NULL; \
	if((str) != NULL) { \
		if((JSSTSstrval=JS_GetStringCharsAndLength((cx), (str), JSSTSlenptr))) { \
225
226
227
			if(*JSSTSlenptr >= (maxsize)) { \
				*JSSTSlenptr = (maxsize)-1; \
			} \
228
			if(((ret)=(char *)alloca(*JSSTSlenptr+1))) { \
229
				for(JSSTSpos=0; JSSTSpos<*JSSTSlenptr; JSSTSpos++) { \
230
					(ret)[JSSTSpos]=(char)JSSTSstrval[JSSTSpos]; \
231
				} \
232
233
				(ret)[*JSSTSlenptr]=0; \
			} \
234
			else JS_ReportError((cx), "Error allocating %lu bytes on stack at %s:%d", (*JSSTSlenptr)+1, getfname(__FILE__), __LINE__); \
235
236
237
238
239
240
241
242
243
244
		} \
	} \
}

#define JSVALUE_TO_ASTRING(cx, val, ret, maxsize, lenptr) \
{ \
	JSString	*JSVTSstr=JS_ValueToString((cx), (val)); \
	JSSTRING_TO_ASTRING((cx), JSVTSstr, (ret), (maxsize), (lenptr)); \
}

rswindell's avatar
rswindell committed
245
246
#endif

247
248
249
250
#ifdef USE_CRYPTLIB
#include <cryptlib.h>
#endif

251
/* xpdev */
252
253
254
#ifndef LINK_LIST_THREADSAFE
 #define LINK_LIST_THREADSAFE
#endif
255
#include "genwrap.h"
rswindell's avatar
rswindell committed
256
#include "semfile.h"
257
#include "netwrap.h"
258
259
#include "dirwrap.h"
#include "filewrap.h"
260
#include "datewrap.h"
261
#include "sockwrap.h"
deuce's avatar
deuce committed
262
#include "multisock.h"
263
#include "eventwrap.h"
264
#include "link_list.h"
265
#include "msg_queue.h"
266
#include "xpdatetime.h"
267
#include "unicode_defs.h"
268

269
270
271
272
273
274
275
276
/***********************/
/* Synchronet-specific */
/***********************/
#include "startup.h"
#ifdef __cplusplus
	#include "threadwrap.h"	/* pthread_mutex_t */
#endif

277
278
279
#include "smblib.h"
#include "ars_defs.h"
#include "scfglib.h"
280
#include "scfgsave.h"
281
282
283
284
285
#include "userdat.h"
#include "riodefs.h"
#include "cmdshell.h"
#include "ringbuf.h"    /* RingBuf definition */
#include "client.h"		/* client_t definition */
286
287
#include "crc16.h"
#include "crc32.h"
288
#include "telnet.h"
289
#include "nopen.h"
290
#include "text.h"
291
292
293
294
295
296
297
#include "str_util.h"
#include "date_str.h"
#include "load_cfg.h"
#include "getstats.h"
#include "msgdate.h"
#include "getmail.h"
#include "msg_id.h"
298

Deucе's avatar
Deucе committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#if defined(JAVASCRIPT)
enum js_event_type {
	JS_EVENT_SOCKET_READABLE_ONCE,
	JS_EVENT_SOCKET_READABLE,
	JS_EVENT_SOCKET_WRITABLE_ONCE,
	JS_EVENT_SOCKET_WRITABLE,
	JS_EVENT_SOCKET_CONNECT,
	JS_EVENT_INTERVAL,
	JS_EVENT_TIMEOUT,
	JS_EVENT_CONSOLE_INPUT_ONCE,
	JS_EVENT_CONSOLE_INPUT
};

struct js_event_interval {
	uint64_t last;	// The tick the last event should have triggered at
	uint64_t period;
};

struct js_event_timeout {
	uint64_t end;	// Time the timeout expires
};

struct js_event_connect {
	SOCKET sv[2];
	SOCKET sock;
};

struct js_event_list {
	struct js_event_list *prev;
	struct js_event_list *next;
	JSFunction *cb;
	JSObject *cx;
	union {
		SOCKET	sock;
		struct js_event_connect connect;
		struct js_event_interval interval;
		struct js_event_timeout timeout;
	} data;
	int32 id;
	enum js_event_type type;
};

struct js_runq_entry {
	JSFunction *func;
	JSObject *cx;
	struct js_runq_entry *next;
};

struct js_listener_entry {
	char *name;
	JSFunction *func;
	int32 id;
	struct js_listener_entry *next;
};

typedef struct js_callback {
	struct js_event_list	*events;
	struct js_runq_entry    *rq_head;
	struct js_runq_entry    *rq_tail;
	struct js_listener_entry *listeners;
	volatile BOOL*	terminated;
	struct js_callback	*parent_cb;
	uint32_t		counter;
	uint32_t		limit;
	uint32_t		yield_interval;
	uint32_t		gc_interval;
	uint32_t		gc_attempts;
	uint32_t		offline_counter;
	int32			next_eid;
	BOOL			auto_terminate;
	BOOL			keepGoing;
	BOOL			bg;
	BOOL			events_supported;
} js_callback_t;
#endif

375
/* Synchronet Node Instance class definition */
376
#if defined(__cplusplus) && defined(JAVASCRIPT)
377
378
379
380
381
382
383
384
385

struct mouse_hotspot {		// Mouse hot-spot
	char	cmd[128];
	long	y;
	long	minx;
	long	maxx;
	bool	hungry;
};

386
387
388
389
390
class sbbs_t
{

public:

deuce's avatar
deuce committed
391
	sbbs_t(ushort node_num, union xp_sockaddr *addr, size_t addr_len, const char* host_name, SOCKET
392
		,scfg_t*, char* text[], client_t* client_info, bool is_event_thread = false);
393
394
	~sbbs_t();

395
396
	bbs_startup_t*	startup;

397
	bool	init(void);
398
	BOOL	terminated;
399
400
401
402

	client_t client;
	SOCKET	client_socket;
	SOCKET	client_socket_dup;
deuce's avatar
deuce committed
403
	union xp_sockaddr	client_addr;
404
	char	client_name[128];
rswindell's avatar
rswindell committed
405
	char	client_ident[128];
deuce's avatar
deuce committed
406
407
	char	client_ipaddr[INET6_ADDRSTRLEN];
	char	local_addr[INET6_ADDRSTRLEN];
408
#ifdef USE_CRYPTLIB
409
	CRYPT_SESSION	ssh_session;
410
#endif
deuce's avatar
deuce committed
411
	int		session_channel;
412
	bool	ssh_mode;
413
	SOCKET	passthru_socket;
414
	bool	passthru_socket_active;
415
	void	passthru_socket_activate(bool);
416
    bool	passthru_thread_running;
417
418
419

	scfg_t	cfg;

420
421
422
423
424
425
426
427
428
	enum ansiState {
		 ansiState_none		// No sequence
		,ansiState_esc		// Escape
		,ansiState_csi		// CSI
		,ansiState_final	// Final byte
		,ansiState_string	// APS, DCS, PM, or OSC
		,ansiState_sos		// SOS
		,ansiState_sos_esc	// ESC inside SOS
	} outchar_esc;			// track ANSI escape seq output
429
430
431
432
433
434

	int 	rioctl(ushort action); // remote i/o control
	bool	rio_abortable;

    RingBuf	inbuf;
    RingBuf	outbuf;
435
	bool	WaitForOutbufEmpty(int timeout) { return WaitForEvent(outbuf.empty_event, timeout) == WAIT_OBJECT_0; }
436
	HANDLE	input_thread;
437
	pthread_mutex_t	input_thread_mutex;
438
	bool	input_thread_mutex_created;
439
	pthread_mutex_t	ssh_mutex;
440
	bool	ssh_mutex_created;
441

442
443
444
445
	#define OUTCOM_RETRY_DELAY		80		// milliseconds
	#define OUTCOM_RETRY_ATTEMPTS	1000	// 80 seconds
	int 	_outcom(uchar ch); 	   // send character, without retry (on buffer flow condition)
	int		outcom(uchar ch, int max_attempts = OUTCOM_RETRY_ATTEMPTS);		// send character, with retry
446
	int 	incom(unsigned long timeout=0);		   // receive character
447

448
	void	spymsg(const char *msg);		// send message to active spies
449

450
	int		putcom(const char *str, size_t len=0);  // Send string
451
452
	void	hangup(void);		   // Hangup modem

453
454
	uchar	telnet_local_option[0x100];
	uchar	telnet_remote_option[0x100];
rswindell's avatar
rswindell committed
455
	void	send_telnet_cmd(uchar cmd, uchar opt);
456
	bool	request_telnet_opt(uchar cmd, uchar opt, unsigned waitforack=0);
457

458
459
460
	uchar	telnet_cmd[64];
	uint	telnet_cmdlen;
	ulong	telnet_cmds_received;
461
	ulong	telnet_mode;
rswindell's avatar
rswindell committed
462
	/* 	input_thread() writes to these variables: */
463
	uchar	telnet_last_rxch;
464
	char	telnet_location[128];
rswindell's avatar
rswindell committed
465
	char	telnet_terminal[TELNET_TERM_MAXLEN+1];
466
	long 	telnet_rows;
rswindell's avatar
rswindell committed
467
468
469
	long	telnet_cols;
	long	telnet_speed;

470
	xpevent_t	telnet_ack_event;
471

472
	time_t	event_time;				// Time of next exclusive event
473
	const char*	event_code;				// Internal code of next exclusive event
474
	bool	is_event_thread;
475
476
	bool	event_thread_running;
    bool	output_thread_running;
477
    bool	input_thread_running;
478
	bool	terminate_output_thread;
479

480
481
482
	JSRuntime*		js_runtime;
	JSContext*		js_cx;
	JSObject*		js_glob;
483
484
485
	JSRuntime*		js_hotkey_runtime;
	JSContext*		js_hotkey_cx;
	JSObject*		js_hotkey_glob;
486
	js_callback_t	js_callback;
487
	long			js_execfile(const char *fname, const char* startup_dir, JSObject* scope = NULL, JSContext* cx = NULL, JSObject* glob = NULL);
488
	long			js_execxtrn(const char *fname, const char* startup_dir);
489
	JSContext*		js_init(JSRuntime**, JSObject**, const char* desc);
490
	void			js_cleanup(void);
491
	bool			js_create_user_objects(JSContext*, JSObject* glob);
492

493
	char	syspage_semfile[MAX_PATH+1];	/* Sysop page semaphore file */
494
495
496
497
498
	char 	menu_dir[128];	/* Over-ride default menu dir */
	char 	menu_file[128]; /* Over-ride menu file */

	user_t	useron; 		/* User currently online */
	node_t	thisnode;		/* Node information */
499
500
501
502
503
504
	smb_t	smb;			/* Currently active message base */
	link_list_t smb_list;
#define SMB_STACK_PUSH	true
#define SMB_STACK_POP	false
	int 	smb_stack(smb_t* smb, bool push);

505
	char	rlogin_name[LEN_ALIAS+1];
506
	char	rlogin_pass[LEN_PASS+1];
507
	char	rlogin_term[TELNET_TERM_MAXLEN+1];	/* RLogin passed terminal type/speed (e.g. "xterm/57600") */
508
509
510
511
512
513
514
515

	uint	temp_dirnum;

	FILE	*nodefile_fp,
			*node_ext_fp,
			*logfile_fp;

	int 	nodefile;		/* File handle for node.dab */
516
	pthread_mutex_t	nodefile_mutex;
517
	int		node_ext;		/* File handle for node.exb */
518
519
	size_t	batup_total();
	size_t	batdn_total();
520
521
522
523

	/*********************************/
	/* Color Configuration Variables */
	/*********************************/
524
525
	char 	*text[TOTAL_TEXT];			/* Text from ctrl\text.dat */
	char 	*text_sav[TOTAL_TEXT];		/* Text from ctrl\text.dat */
526

527
	char 	dszlog[127];	/* DSZLOG environment variable */
528
    int     keybuftop,keybufbot;    /* Keyboard input buffer pointers (for ungetkey) */
529
	char    keybuf[KEY_BUFSIZE];    /* Keyboard input buffer */
530
531
	size_t	keybuf_space(void);
	size_t	keybuf_level(void);
532
533

	ushort	node_connection;
534
	char	connection[LEN_MODEM+1];	/* Connection Description */
535
536
537
538
539
	ulong	cur_rate;		/* Current Connection (DCE) Rate */
	ulong	cur_cps;		/* Current Average Transfer CPS */
	ulong	dte_rate;		/* Current COM Port (DTE) Rate */
	time_t 	timeout;		/* User inactivity timeout reference */
	ulong 	timeleft_warn;	/* low timeleft warning flag */
rswindell's avatar
rswindell committed
540
541
	uint	curatr; 		/* Current Text Attributes Always */
	uint	attr_stack[64];	/* Saved attributes (stack) */
542
	int 	attr_sp;		/* Attribute stack pointer */
543
	long 	lncntr; 		/* Line Counter - for PAUSE */
544
	bool	msghdr_tos;		/* Message header was displayed at Top of Screen */
rswindell's avatar
rswindell committed
545
	long	row;			/* Current row */
546
547
	long 	rows;			/* Current number of Rows for User */
	long	cols;			/* Current number of Columns for User */
548
	long	column;			/* Current column counter (for line counter) */
rswindell's avatar
rswindell committed
549
	long	tabstop;		/* Current symmetric-tabstop (size) */
550
	long	lastlinelen;	/* The previously displayed line length */
551
	long 	autoterm;		/* Auto-detected terminal type */
rswindell's avatar
rswindell committed
552
	char	terminal[TELNET_TERM_MAXLEN+1];	// <- answer() writes to this
553
	long	cterm_version;	/* (MajorVer*1000) + MinorVer */
554
	link_list_t savedlines;
555
556
	char 	lbuf[LINE_BUFSIZE+1];/* Temp storage for each line output */
	int		lbuflen;		/* Number of characters in line buffer */
rswindell's avatar
rswindell committed
557
	uint	latr;			/* Starting attribute of line buffer */
558
559
	ulong	console;		/* Defines current Console settings */
	char 	wordwrap[81];	/* Word wrap buffer */
560
	time_t	now,			/* Used to store current time in Unix format */
561
			last_sysop_auth,/* Time sysop was last authenticated */
562
			answertime, 	/* Time call was answered */
563
564
			logontime,		/* Time user logged on */
			starttime,		/* Time stamp to use for time left calcs */
565
			ns_time,		/* File new-scan time */
566
567
568
569
			last_ns_time;	/* Most recent new-file-scan this call */
	uchar 	action;			/* Current action of user */
	long 	online; 		/* Remote/Local or not online */
	long 	sys_status; 	/* System Status */
570
	subscan_t	*subscan;	/* User sub configuration/scan info */
571

572
	int64_t	logon_ulb,		/* Upload Bytes This Call */
573
574
			logon_dlb,		/* Download Bytes This Call */
			logon_uls,		/* Uploads This Call */
575
576
			logon_dls;		/* Downloads This Call */
	ulong	logon_posts,	/* Posts This Call */
577
578
			logon_emails,	/* Emails This Call */
			logon_fbacks;	/* Feedbacks This Call */
579
	uchar	logon_ml;		/* Security level of the user upon logon */
580
581
582
583
584
585
586

	uint 	main_cmds;		/* Number of Main Commands this call */
	uint 	xfer_cmds;		/* Number of Xfer Commands this call */
	ulong	posts_read; 	/* Number of Posts read this call */
	char 	temp_uler[31];  /* User who uploaded the files to temp dir */
	char 	temp_file[41];	/* Origin of extracted temp files */
	long 	temp_cdt;		/* Credit value of file that was extracted */
587
	bool 	autohang;		/* Used for auto-hangup after transfer */
588
589
590
	size_t 	logcol; 		/* Current column of log file */
	uint 	criterrs; 		/* Critical error counter */

591
592
593
594
595
596
	uint 	curgrp; 		/* Current group */
	uint	*cursub;		/* Current sub-board for each group */
	uint	curlib; 		/* Current library */
	uint	*curdir;		/* Current directory for each library */
	uint 	*usrgrp;		/* Real group numbers */
	uint	usrgrps;		/* Number groups this user has access to */
597
	uint	usrgrp_total;	/* Total number of groups */
598
599
	uint 	*usrlib;		/* Real library numbers */
	uint	usrlibs;		/* Number of libs this user can access */
600
	uint	usrlib_total;	/* Total number of libraries */
601
602
603
604
	uint 	**usrsub;		/* Real sub numbers */
	uint	*usrsubs;		/* Num of subs with access for each grp */
	uint 	**usrdir;		/* Real dir numbers */
	uint	*usrdirs;		/* Num of dirs with access for each lib */
605
606
607
	uint	cursubnum;		/* For ARS */
	uint	curdirnum;		/* For ARS */
	ulong 	timeleft;		/* Number of seconds user has left online */
608

609
610
611
612
613
614
615
616
	char 	*comspec;		/* Pointer to environment variable COMSPEC */
	char 	cid[LEN_CID+1]; /* Caller ID (IP Address) of current caller */
	char 	*noaccess_str;	/* Why access was denied via ARS */
	long 	noaccess_val;	/* Value of parameter not met in ARS */
	int		errorlevel; 	/* Error level of external program */

	csi_t	main_csi;		/* Main Command Shell Image */

617
	smbmsg_t*	current_msg;	/* For message header @-codes */
rswindell's avatar
rswindell committed
618
619
620
	const char*	current_msg_subj;
	const char*	current_msg_from;
	const char*	current_msg_to;
621
	file_t*	current_file;	
622

623
624
625
			/* Global command shell variables */
	uint	global_str_vars;
	char **	global_str_var;
rswindell's avatar
rswindell committed
626
	uint32_t *	global_str_var_name;
627
	uint	global_int_vars;
deuce's avatar
deuce committed
628
	int32_t *	global_int_var;
rswindell's avatar
rswindell committed
629
	uint32_t *	global_int_var_name;
630
631
	char *	sysvar_p[MAX_SYSVARS];
	uint	sysvar_pi;
deuce's avatar
deuce committed
632
	int32_t	sysvar_l[MAX_SYSVARS];
633
634
635
	uint	sysvar_li;

    /* ansi_term.cpp */
636
637
	const char*	ansi(int atr);			/* Returns ansi escape sequence for atr */
	char*	ansi(int atr, int curatr, char* str);
638
639
640
641
    bool	ansi_gotoxy(int x, int y);
	bool	ansi_getxy(int* x, int* y);
	bool	ansi_save(void);
	bool	ansi_restore(void);
642
	void	ansi_getlines(void);
643
644
645
646
647
648
649
	enum ansi_mouse_mode {
		ANSI_MOUSE_X10	= 9,
		ANSI_MOUSE_NORM	= 1000,
		ANSI_MOUSE_BTN	= 1002,
		ANSI_MOUSE_ANY	= 1003,
		ANSI_MOUSE_EXT	= 1006
	};
rswindell's avatar
rswindell committed
650
	int		ansi_mouse(enum ansi_mouse_mode, bool enable);
651
652
653
654

			/* Command Shell Methods */
	int		exec(csi_t *csi);
	int		exec_function(csi_t *csi);
655
	int		exec_misc(csi_t *csi, const char *path);
rswindell's avatar
rswindell committed
656
657
658
	int		exec_net(csi_t *csi);
	int		exec_msg(csi_t *csi);
	int		exec_file(csi_t *csi);
659
	long	exec_bin(const char *mod, csi_t *csi, const char* startup_dir=NULL);
660
661
	void	clearvars(csi_t *bin);
	void	freevars(csi_t *bin);
deuce's avatar
deuce committed
662
663
	char**	getstrvar(csi_t *bin, uint32_t name);
	int32_t*	getintvar(csi_t *bin, uint32_t name);
664
665
	char*	copystrvar(csi_t *csi, char *p, char *str);
	void	skipto(csi_t *csi, uchar inst);
666
	bool	ftp_cmd(csi_t* csi, SOCKET ctrl_sock, const char* cmdsrc, char* rsp);
rswindell's avatar
rswindell committed
667
	bool	ftp_put(csi_t* csi, SOCKET ctrl_sock, char* src, char* dest);
668
669
670
	bool	ftp_get(csi_t* csi, SOCKET ctrl_sock, char* src, char* dest, bool dir=false);
	SOCKET	ftp_data_sock(csi_t* csi, SOCKET ctrl_sock, SOCKADDR_IN*);

671
672
673
	bool	select_shell(void);
	bool	select_editor(void);

674
675
676
	void	sys_info(void);
	void	user_info(void);
	void	xfer_policy(void);
677
678

	void	xfer_prot_menu(enum XFER_TYPE);
679
680
	void	node_stats(uint node_num);
	void	sys_stats(void);
681
	void	logonlist(const char* args = "");
682
	bool	spy(uint node_num);
683
684
685

	void	reset_logon_vars(void);

686
	uint	finduser(const char* str, bool silent_failure = false);
687
688
689
690
691
692
693
694
695

	int 	sub_op(uint subnum);

	int		dir_op(uint dirnum);

	void	getmsgptrs(void);
	void	putmsgptrs(void);
	void	getusrsubs(void);
	void	getusrdirs(void);
696
697
	uint	getusrsub(uint subnum);
	uint	getusrgrp(uint subnum);
698
699
	uint	getusrdir(uint dirnum);
	uint	getusrlib(uint dirnum);
700

701
	uint	userdatdupe(uint usernumber, uint offset, uint datlen, char *dat
702
				,bool del=false, bool next=false);
703
	ulong	gettimeleft(bool handle_out_of_time=true);
704
705
706
	bool	gettimeleft_inside;

	/* str.cpp */
707
	char*	server_host_name(void);
708
709
	char*	timestr(time_t);
	char*	datestr(time_t);
710
    char	timestr_output[60];
711
	char	datestr_output[60];
712
	char*	age_of_posted_item(char* buf, size_t max, time_t);
713
	void	userlist(long mode);
714
	size_t	gettmplt(char *outstr, const char *tmplt, long mode);
715
	void	sif(char *fname, char *answers, long len);	/* Synchronet Interface File */
716
717
718
719
	void	sof(char *fname, char *answers, long len);
	void	create_sif_dat(char *siffile, char *datfile);
	void	read_sif_dat(char *siffile, char *datfile);
	void	printnodedat(uint number, node_t* node);
deuce's avatar
deuce committed
720
	bool	inputnstime32(time32_t *dt);
721
	bool	inputnstime(time_t *dt);
722
	bool	chkpass(char *pass, user_t* user, bool unique);
723
	char *	cmdstr(const char *instr, const char *fpath, const char *fspec, char *outstr, long mode = EX_UNSPECIFIED);
724
725
726
727
	char	cmdstr_output[512];

	void	subinfo(uint subnum);
	void	dirinfo(uint dirnum);
728
	bool	trashcan(const char *insearch, const char *name);
729
730
	void	time_bank(void);
	void	change_user(void);
731
732
733

	/* writemsg.cpp */
	void	automsg(void);
734
	bool	writemsg(const char *str, const char *top, char *subj, long mode, uint subnum
735
				,const char *to, const char* from, const char** editor=NULL, const char** charset=NULL);
736
	char*	quotes_fname(int xedit, char* buf, size_t len);
737
	char*	msg_tmp_fname(int xedit, char* fname, size_t len);
738
	char	putmsg(const char *str, long mode, long org_cols = 0, JSObject* obj = NULL);
739
	char	putmsgfrag(const char* str, long* mode, long org_cols = 0, JSObject* obj = NULL);
740
	bool	msgabort(void);
741
742
	bool	email(int usernumber, const char *top = NULL, const char *title = NULL
				, long mode = WM_NONE, smb_t* resmb = NULL, smbmsg_t* remsg = NULL);
743
	bool	forwardmsg(smb_t*, smbmsg_t*, const char* to, const char* subject = NULL, const char* comment = NULL);
744
	void	removeline(char *str, char *str2, char num, char skip);
745
	ulong	msgeditor(char *buf, const char *top, char *title);
746
	bool	editfile(char *path, bool msg=false);
rswindell's avatar
rswindell committed
747
	ushort	chmsgattr(smbmsg_t);
748
	bool	quotemsg(smb_t*, smbmsg_t*, bool tails = false);
749
	bool	editmsg(smb_t*, smbmsg_t*);
750
	void	editor_inf(int xeditnum, const char *to, const char* from, const char *subj, long mode
751
				,uint subnum, const char* tagfile);
752
	bool	copyfattach(uint to, uint from, const char* subj);
753
	bool	movemsg(smbmsg_t* msg, uint subnum);
754
755
	int		process_edited_text(char* buf, FILE* stream, long mode, unsigned* lines, unsigned maxlines);
	int		process_edited_file(const char* src, const char* dest, long mode, unsigned* lines, unsigned maxlines);
756
	void	editor_info_to_msg(smbmsg_t*, const char* editor, const char* charset);
757
	char	editor_details[128];
758

759
	/* postmsg.cpp */
760
	bool	postmsg(uint subnum, long wm_mode = WM_NONE, smb_t* resmb = NULL, smbmsg_t* remsg = NULL);
761

762
763
764
	/* mail.cpp */
	int		delmail(uint usernumber,int which);
	void	telluser(smbmsg_t* msg);
765
	void	delallmail(uint usernumber, int which, bool permanent=true, long lm_mode = 0);
766
767

	/* getmsg.cpp */
768
	int		loadmsg(smbmsg_t *msg, ulong number);
rswindell's avatar
rswindell committed
769
	void	show_msgattr(smbmsg_t*);
770
	void	show_msghdr(smb_t*, smbmsg_t*, const char *subj = NULL, const char* from = NULL, const char* to = NULL);
rswindell's avatar
rswindell committed
771
772
	bool	show_msg(smb_t*, smbmsg_t*, long p_mode = 0, post_t* post = NULL);
	bool	msgtotxt(smb_t*, smbmsg_t*, const char *fname, bool header = true, ulong gettxt_mode = GETMSGTXT_ALL);
773
774
	const char* msghdr_text(const smbmsg_t*, uint index);
	char	msghdr_utf8_text[128];
rswindell's avatar
rswindell committed
775
776
	const char* msghdr_field(const smbmsg_t*, const char* str, char* buf = NULL, bool can_utf8 = false);
	char	msgghdr_field_cp437_str[128];
777
778
779
	ulong	getlastmsg(uint subnum, uint32_t *ptr, time_t *t);
	time_t	getmsgtime(uint subnum, ulong ptr);
	ulong	getmsgnum(uint subnum, time_t t);
780
	void	download_msg_attachments(smb_t*, smbmsg_t*, bool del);
781
782

	/* readmail.cpp */
rswindell's avatar
rswindell committed
783
	void	readmail(uint usernumber, int which, long lm_mode = 0);
784
	bool	readmail_inside;
785
	long	searchmail(mail_t*, long start, long msgss, int which, const char *search, const char* order);
786
787

	/* bulkmail.cpp */
788
789
	bool	bulkmail(uchar *ar);
	int		bulkmailhdr(smb_t*, smbmsg_t*, uint usernum);
790
791

	/* con_out.cpp */
rswindell's avatar
rswindell committed
792
	size_t	bstrlen(const char *str, long mode = 0);
rswindell's avatar
rswindell committed
793
	int		bputs(const char *str, long mode = 0);	/* BBS puts function */
794
	int		bputs(long mode, const char* str) { return bputs(str, mode); }
795
	int		rputs(const char *str, size_t len=0);	/* BBS raw puts function */
796
	int		rputs(long mode, const char* str) { return rputs(str, mode); }
797
798
799
	int		bprintf(const char *fmt, ...)			/* BBS printf function */
#if defined(__GNUC__)   // Catch printf-format errors
    __attribute__ ((format (printf, 2, 3)));		// 1 is 'this'
rswindell's avatar
rswindell committed
800
801
802
803
804
#endif
	;
	int		bprintf(long mode, const char *fmt, ...)
#if defined(__GNUC__)   // Catch printf-format errors
    __attribute__ ((format (printf, 3, 4)));		// 1 is 'this', 2 is 'mode'
805
806
807
808
809
#endif
	;
	int		rprintf(const char *fmt, ...)			/* BBS raw printf function */
#if defined(__GNUC__)   // Catch printf-format errors
    __attribute__ ((format (printf, 2, 3)));		// 1 is 'this'
810
811
812
813
814
#endif
	;
	int		comprintf(const char *fmt, ...)			/* BBS direct-comm printf function */
#if defined(__GNUC__)   // Catch printf-format errors
    __attribute__ ((format (printf, 2, 3)));		// 1 is 'this'
815
816
#endif
	;
817
	void	backspace(int count=1);			/* Output destructive backspace(s) via outchar */
818
	int		outchar(char ch);				/* Output a char - check echo and emu.  */
819
	int		outchar(enum unicode_codepoint, char cp437_fallback);
820
	int		outchar(enum unicode_codepoint, const char* cp437_fallback = NULL);
rswindell's avatar
rswindell committed
821
	void	inc_row(int count);
822
	void	inc_column(int count);
Rob Swindell's avatar
Rob Swindell committed
823
	void	center(const char *str, unsigned int columns = 0);
rswindell's avatar
rswindell committed
824
	void	wide(const char*);
rswindell's avatar
rswindell committed
825
	void	clearscreen(long term);
826
827
	void	clearline(void);
	void	cleartoeol(void);
rswindell's avatar
rswindell committed
828
	void	cleartoeos(void);
829
830
831
832
833
	void	cursor_home(void);
	void	cursor_up(int count=1);
	void	cursor_down(int count=1);
	void	cursor_left(int count=1);
	void	cursor_right(int count=1);
834
	bool	cursor_xy(int x, int y);
835
	bool	cursor_getxy(int* x, int* y);
836
837
838
	void	carriage_return(int count=1);
	void	line_feed(int count=1);
	void	newline(int count=1);
839
840
841
	void	cond_newline() { if(column > 0) newline(); }
	void	cond_blankline() { if(column > 0) newline(); if(lastlinelen) newline(); }
	void	cond_contline() { if(column > 0 && cols < TERM_COLS_DEFAULT) bputs(text[LongLineContinuationPrefix]); }
842
	long	term_supports(long cmp_flags=0);
843
844
	const char* term_type(long term_supports = -1);
	const char* term_charset(long term_supports = -1);
845
	bool	update_nodeterm(void);
846
	int		backfill(const char* str, float pct, int full_attr, int empty_attr);
847
	void	progress(const char* str, int count, int total, int interval=1);
848
849
	bool	saveline(void);
	bool	restoreline(void);
850
	int		petscii_to_ansibbs(unsigned char);
rswindell's avatar
rswindell committed
851
	size_t	print_utf8_as_cp437(const char*, size_t);
852
853
	int		attr(int);				/* Change text color/attributes */
	void	ctrl_a(char);			/* Performs Ctrl-Ax attribute changes */
rswindell's avatar
rswindell committed
854
	char*	auto_utf8(const char*, long* mode);
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
	enum output_rate {
		output_rate_unlimited,
		output_rate_300 = 300,
		output_rate_600 = 600,
		output_rate_1200 = 1200,
		output_rate_2400 = 2400,
		output_rate_4800 = 4800,
		output_rate_9600 = 9600,
		output_rate_19200 = 19200,
		output_rate_38400 = 38400,
		output_rate_57600 = 57600,
		output_rate_76800 = 76800,
		output_rate_115200 = 115200,
	} cur_output_rate;
	void	set_output_rate(enum output_rate);
870
871

	/* getstr.cpp */
872
	size_t	getstr_offset;
873
	size_t	getstr(char *str, size_t length, long mode, const str_list_t history = NULL);
874
	long	getnum(ulong max, ulong dflt=0);
875
	void	insert_indicator(void);
876
877

	/* getkey.cpp */
878
	char	getkey(long mode); 		/* Waits for a key hit local or remote  */
879
	long	getkeys(const char *str, ulong max, long mode = K_UPPER);
880
	void	ungetkey(char ch, bool insert = false);		/* Places 'ch' into the input buffer    */
rswindell's avatar
rswindell committed
881
	void	ungetstr(const char* str, bool insert = false);
882
	char	question[MAX_TEXTDAT_ITEM_LEN+1];
883
884
	bool	yesno(const char *str, long mode = 0);
	bool	noyes(const char *str, long mode = 0);
rswindell's avatar
rswindell committed
885
	bool	pause_inside;
886
	void	pause(void);
887
888
	const char *	mnestr;
	void	mnemonics(const char *str);
889

rswindell's avatar
rswindell committed
890
	/* inkey.cpp */
891
	int		inkey(long mode, unsigned long timeout=0);
rswindell's avatar
rswindell committed
892
	char	handle_ctrlkey(char ch, long mode=0);
893
894
895
896
897
898
899
900
901

									// Terminal mouse reporting mode (mouse_mode)
#define MOUSE_MODE_OFF		0		// No terminal mouse reporting enabled/expected
#define MOUSE_MODE_X10		(1<<0)	// X10 compatible mouse reporting enabled
#define MOUSE_MODE_NORM		(1<<1)	// Normal tracking mode mouse reporting
#define MOUSE_MODE_BTN		(1<<2)	// Button-event tracking mode mouse reporting
#define MOUSE_MODE_ANY		(1<<3)	// Any-event tracking mode mouse reporting
#define MOUSE_MODE_EXT		(1<<4)	// SGR-encoded extended coordinate mouse reporting

rswindell's avatar
rswindell committed
902
	long	mouse_mode;			// Mouse reporting mode flags
rswindell's avatar
rswindell committed
903
	uint	hot_attr;			// Auto-Mouse hot-spot attribute (when non-zero)
904
	bool	hungry_hotspots;
rswindell's avatar
rswindell committed
905
	link_list_t mouse_hotspots;	// Mouse hot-spots
906
	struct mouse_hotspot* pause_hotspot;
rswindell's avatar
rswindell committed
907
	struct mouse_hotspot* add_hotspot(struct mouse_hotspot*);
908
909
910
	struct mouse_hotspot* add_hotspot(char cmd, bool hungry = true, long minx = -1, long maxx = -1, long y = -1);
	struct mouse_hotspot* add_hotspot(ulong num, bool hungry = true, long minx = -1, long maxx = -1, long y = -1);
	struct mouse_hotspot* add_hotspot(const char* cmd, bool hungry = true, long minx = -1, long maxx = -1, long y = -1);
rswindell's avatar
rswindell committed
911
912
913
	void	clear_hotspots(void);
	void	scroll_hotspots(long count);
	void	set_mouse(long mode);
rswindell's avatar
rswindell committed
914

915
	/* prntfile.cpp */
916
917
918
	bool	printfile(const char* fname, long mode, long org_cols = 0, JSObject* obj = NULL);
	bool	printtail(const char* fname, int lines, long mode, long org_cols = 0, JSObject* obj = NULL);
	bool	menu(const char *code, long mode = 0, JSObject* obj = NULL);
919
	bool	random_menu(const char *code, long mode = 0, JSObject* obj = NULL);
920
	bool	menu_exists(const char *code, const char* ext=NULL, char* realpath=NULL);
921

922
	int		uselect(int add, uint n, const char *title, const char *item, const uchar *ar);
923
924
	uint	uselect_total, uselect_num[500];

925
926
	long	mselect(const char *title, str_list_t list, unsigned max_selections, const char* item_fmt, const char* selected_str, const char* unselected_str, const char* prompt_fmt);

927
928
929
	void	redrwstr(char *strin, int i, int l, long mode);

	/* atcodes.cpp */
930
931
	int		show_atcode(const char *code, JSObject* obj = NULL);
	const char*	atcode(char* sp, char* str, size_t maxlen, long* pmode = NULL, bool centered = false, JSObject* obj = NULL);
932
933

	/* getnode.cpp */
934
935
	int		getsmsg(int usernumber, bool clearline = false);
	int		getnmsg(bool clearline = false);
936
	int		whos_online(bool listself);/* Lists active nodes, returns active nodes */
937
	void	nodelist(void);
938
939
	int		getnodeext(uint number, char * str);
	int		getnodedat(uint number, node_t * node, bool lock);
940
	void	nodesync(bool clearline = false);
941
942
	user_t	nodesync_user;
	bool	nodesync_inside;
943
	uint	count_nodes(bool self = true);
944
945
946
947

	/* putnode.cpp */
	int		putnodedat(uint number, node_t * node);
	int		putnodeext(uint number, char * str);
948

949
	/* login.ccp */
950
	int		login(char *user_name, char *pw_prompt, const char* user_pw = NULL, const char* sys_pw = NULL);
951
	void	badlogin(char* user, char* passwd, const char* protocol=NULL, xp_sockaddr* addr=NULL, bool delay=true);
952
	char*	parse_login(char*);
953
954

	/* answer.cpp */
955
	bool	answer(void);
956
957

	/* logon.ccp */
958
	bool	logon(void);
959
960

	/* logout.cpp */
961
962
	void	logout(void);

963
964
965
	/* newuser.cpp */
	BOOL	newuser(void);					/* Get new user							*/

966
	/* text_sec.cpp */
967
	int		text_sec(void);						/* Text sections */
968
969

	/* readmsgs.cpp */
970
	post_t* loadposts(uint32_t *posts, uint subnum, ulong ptr, long mode, ulong *unvalidated_num, uint32_t* visible=NULL);
971
	int		scanposts(uint subnum, long mode, const char* find);	/* Scan sub-board */
972
	bool	scanposts_inside;
973
	long	listsub(uint subnum, long mode, long start, const char* search);
974
	long	listmsgs(uint subnum, long mode, post_t* post, long start, long posts, bool reading = true);
975
	long	searchposts(uint subnum, post_t* post, long start, long msgs, const char* find);