sbbs.h 50.3 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
298
#include "str_util.h"
#include "date_str.h"
#include "load_cfg.h"
#include "filedat.h"
#include "getstats.h"
#include "msgdate.h"
#include "getmail.h"
#include "msg_id.h"
299

300
/* Synchronet Node Instance class definition */
301
#if defined(__cplusplus) && defined(JAVASCRIPT)
302
303
304
305
306
307
308
309
310

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

311
312
313
314
315
class sbbs_t
{

public:

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

320
321
	bbs_startup_t*	startup;

322
	bool	init(void);
323
	BOOL	terminated;
324
325
326
327

	client_t client;
	SOCKET	client_socket;
	SOCKET	client_socket_dup;
deuce's avatar
deuce committed
328
	union xp_sockaddr	client_addr;
329
	char	client_name[128];
rswindell's avatar
rswindell committed
330
	char	client_ident[128];
deuce's avatar
deuce committed
331
332
	char	client_ipaddr[INET6_ADDRSTRLEN];
	char	local_addr[INET6_ADDRSTRLEN];
333
#ifdef USE_CRYPTLIB
334
	CRYPT_SESSION	ssh_session;
335
#endif
deuce's avatar
deuce committed
336
	int		session_channel;
337
	bool	ssh_mode;
338
	SOCKET	passthru_socket;
339
	bool	passthru_socket_active;
340
	void	passthru_socket_activate(bool);
341
    bool	passthru_thread_running;
342
343
344

	scfg_t	cfg;

345
346
347
348
349
350
351
352
353
	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
354
355
356
357
358
359
360

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

    RingBuf	inbuf;
    RingBuf	outbuf;
	HANDLE	input_thread;
361
	pthread_mutex_t	input_thread_mutex;
362
	bool	input_thread_mutex_created;
363
	pthread_mutex_t	ssh_mutex;
364
	bool	ssh_mutex_created;
365

366
367
368
369
	#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
370
	int 	incom(unsigned long timeout=0);		   // receive character
371

372
	void	spymsg(const char *msg);		// send message to active spies
373

374
	int		putcom(const char *str, size_t len=0);  // Send string
375
376
	void	hangup(void);		   // Hangup modem

377
378
	uchar	telnet_local_option[0x100];
	uchar	telnet_remote_option[0x100];
rswindell's avatar
rswindell committed
379
	void	send_telnet_cmd(uchar cmd, uchar opt);
380
	bool	request_telnet_opt(uchar cmd, uchar opt, unsigned waitforack=0);
381

382
383
384
	uchar	telnet_cmd[64];
	uint	telnet_cmdlen;
	ulong	telnet_cmds_received;
385
	ulong	telnet_mode;
rswindell's avatar
rswindell committed
386
	/* 	input_thread() writes to these variables: */
387
	uchar	telnet_last_rxch;
388
	char	telnet_location[128];
rswindell's avatar
rswindell committed
389
	char	telnet_terminal[TELNET_TERM_MAXLEN+1];
390
	long 	telnet_rows;
rswindell's avatar
rswindell committed
391
392
393
	long	telnet_cols;
	long	telnet_speed;

394
	xpevent_t	telnet_ack_event;
395

396
	time_t	event_time;				// Time of next exclusive event
397
	const char*	event_code;				// Internal code of next exclusive event
398
	bool	is_event_thread;
399
400
	bool	event_thread_running;
    bool	output_thread_running;
401
    bool	input_thread_running;
402
	bool	terminate_output_thread;
403

404
405
406
	JSRuntime*		js_runtime;
	JSContext*		js_cx;
	JSObject*		js_glob;
407
408
409
	JSRuntime*		js_hotkey_runtime;
	JSContext*		js_hotkey_cx;
	JSObject*		js_hotkey_glob;
410
	js_callback_t	js_callback;
411
	long			js_execfile(const char *fname, const char* startup_dir, JSObject* scope = NULL, JSContext* cx = NULL, JSObject* glob = NULL);
412
	long			js_execxtrn(const char *fname, const char* startup_dir);
413
	JSContext*		js_init(JSRuntime**, JSObject**, const char* desc);
414
	void			js_cleanup(void);
415
	bool			js_create_user_objects(JSContext*, JSObject* glob);
416

417
	char	syspage_semfile[MAX_PATH+1];	/* Sysop page semaphore file */
418
419
420
421
422
	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 */
423
424
425
426
427
428
	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);

429
	char	rlogin_name[LEN_ALIAS+1];
430
	char	rlogin_pass[LEN_PASS+1];
431
	char	rlogin_term[TELNET_TERM_MAXLEN+1];	/* RLogin passed terminal type/speed (e.g. "xterm/57600") */
432
433
434
435
436
437
438
439

	uint	temp_dirnum;

	FILE	*nodefile_fp,
			*node_ext_fp,
			*logfile_fp;

	int 	nodefile;		/* File handle for node.dab */
440
	pthread_mutex_t	nodefile_mutex;
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
	int		node_ext;		/* File handle for node.exb */

							/* Batch download queue */
	char 	**batdn_name;	/* Filenames */
	ushort	*batdn_alt; 	/* Alternate path */
	uint 	*batdn_dir, 	/* Directory for each file */
			 batdn_total;	/* Total files */
	long 	*batdn_offset;	/* Offset for data */
	ulong	*batdn_size;	/* Size of file in bytes */
	ulong	*batdn_cdt; 	/* Credit value of file */

							/* Batch upload queue */
	char 	**batup_desc,	/* Description for each file */
			**batup_name;	/* Filenames */
	long	*batup_misc;	/* Miscellaneous bits */
	ushort	*batup_alt; 	/* Alternate path */
	uint 	*batup_dir, 	/* Directory for each file */
			batup_total;	/* Total files */

	/*********************************/
	/* Color Configuration Variables */
	/*********************************/
463
464
	char 	*text[TOTAL_TEXT];			/* Text from ctrl\text.dat */
	char 	*text_sav[TOTAL_TEXT];		/* Text from ctrl\text.dat */
465

466
	char 	dszlog[127];	/* DSZLOG environment variable */
467
    int     keybuftop,keybufbot;    /* Keyboard input buffer pointers (for ungetkey) */
468
	char    keybuf[KEY_BUFSIZE];    /* Keyboard input buffer */
469
470
	size_t	keybuf_space(void);
	size_t	keybuf_level(void);
471
472

	ushort	node_connection;
473
	char	connection[LEN_MODEM+1];	/* Connection Description */
474
475
476
477
478
	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
479
480
	uint	curatr; 		/* Current Text Attributes Always */
	uint	attr_stack[64];	/* Saved attributes (stack) */
481
	int 	attr_sp;		/* Attribute stack pointer */
482
	long 	lncntr; 		/* Line Counter - for PAUSE */
483
	bool	msghdr_tos;		/* Message header was displayed at Top of Screen */
rswindell's avatar
rswindell committed
484
	long	row;			/* Current row */
485
486
	long 	rows;			/* Current number of Rows for User */
	long	cols;			/* Current number of Columns for User */
487
	long	column;			/* Current column counter (for line counter) */
rswindell's avatar
rswindell committed
488
	long	tabstop;		/* Current symmetric-tabstop (size) */
489
	long	lastlinelen;	/* The previously displayed line length */
490
	long 	autoterm;		/* Auto-detected terminal type */
rswindell's avatar
rswindell committed
491
	char	terminal[TELNET_TERM_MAXLEN+1];	// <- answer() writes to this
492
	long	cterm_version;	/* (MajorVer*1000) + MinorVer */
493
	link_list_t savedlines;
494
495
	char 	lbuf[LINE_BUFSIZE+1];/* Temp storage for each line output */
	int		lbuflen;		/* Number of characters in line buffer */
rswindell's avatar
rswindell committed
496
	uint	latr;			/* Starting attribute of line buffer */
497
498
	ulong	console;		/* Defines current Console settings */
	char 	wordwrap[81];	/* Word wrap buffer */
499
	time_t	now,			/* Used to store current time in Unix format */
500
			last_sysop_auth,/* Time sysop was last authenticated */
501
			answertime, 	/* Time call was answered */
502
503
			logontime,		/* Time user logged on */
			starttime,		/* Time stamp to use for time left calcs */
504
			ns_time,		/* File new-scan time */
505
506
507
508
			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 */
509
	subscan_t	*subscan;	/* User sub configuration/scan info */
510
511
512
513
514
515
516
517

	ulong	logon_ulb,		/* Upload Bytes This Call */
			logon_dlb,		/* Download Bytes This Call */
			logon_uls,		/* Uploads This Call */
			logon_dls,		/* Downloads This Call */
			logon_posts,	/* Posts This Call */
			logon_emails,	/* Emails This Call */
			logon_fbacks;	/* Feedbacks This Call */
518
	uchar	logon_ml;		/* ML of the user upon logon */
519
520
521
522
523
524
525

	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 */
526
	bool 	autohang;		/* Used for auto-hangup after transfer */
527
528
529
	size_t 	logcol; 		/* Current column of log file */
	uint 	criterrs; 		/* Critical error counter */

530
531
532
533
534
535
	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 */
536
	uint	usrgrp_total;	/* Total number of groups */
537
538
	uint 	*usrlib;		/* Real library numbers */
	uint	usrlibs;		/* Number of libs this user can access */
539
	uint	usrlib_total;	/* Total number of libraries */
540
541
542
543
	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 */
544
545
546
	uint	cursubnum;		/* For ARS */
	uint	curdirnum;		/* For ARS */
	ulong 	timeleft;		/* Number of seconds user has left online */
547

548
549
550
551
552
553
554
555
556
	char 	*comspec;		/* Pointer to environment variable COMSPEC */
	ushort	altul;			/* Upload to alternate path flag */
	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 */

557
	smbmsg_t*	current_msg;	/* For message header @-codes */
rswindell's avatar
rswindell committed
558
559
560
	const char*	current_msg_subj;
	const char*	current_msg_from;
	const char*	current_msg_to;
561
	file_t*		current_file;
562

563
564
565
			/* Global command shell variables */
	uint	global_str_vars;
	char **	global_str_var;
rswindell's avatar
rswindell committed
566
	uint32_t *	global_str_var_name;
567
	uint	global_int_vars;
deuce's avatar
deuce committed
568
	int32_t *	global_int_var;
rswindell's avatar
rswindell committed
569
	uint32_t *	global_int_var_name;
570
571
	char *	sysvar_p[MAX_SYSVARS];
	uint	sysvar_pi;
deuce's avatar
deuce committed
572
	int32_t	sysvar_l[MAX_SYSVARS];
573
574
575
	uint	sysvar_li;

    /* ansi_term.cpp */
576
577
	const char*	ansi(int atr);			/* Returns ansi escape sequence for atr */
	char*	ansi(int atr, int curatr, char* str);
578
579
580
581
    bool	ansi_gotoxy(int x, int y);
	bool	ansi_getxy(int* x, int* y);
	bool	ansi_save(void);
	bool	ansi_restore(void);
582
	void	ansi_getlines(void);
583
584
585
586
587
588
589
	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
590
	int		ansi_mouse(enum ansi_mouse_mode, bool enable);
591
592
593
594
595

			/* Command Shell Methods */
	int		exec(csi_t *csi);
	int		exec_function(csi_t *csi);
	int		exec_misc(csi_t *csi, char *path);
rswindell's avatar
rswindell committed
596
597
598
	int		exec_net(csi_t *csi);
	int		exec_msg(csi_t *csi);
	int		exec_file(csi_t *csi);
599
	long	exec_bin(const char *mod, csi_t *csi, const char* startup_dir=NULL);
600
601
	void	clearvars(csi_t *bin);
	void	freevars(csi_t *bin);
deuce's avatar
deuce committed
602
603
	char**	getstrvar(csi_t *bin, uint32_t name);
	int32_t*	getintvar(csi_t *bin, uint32_t name);
604
605
	char*	copystrvar(csi_t *csi, char *p, char *str);
	void	skipto(csi_t *csi, uchar inst);
606
	bool	ftp_cmd(csi_t* csi, SOCKET ctrl_sock, const char* cmdsrc, char* rsp);
rswindell's avatar
rswindell committed
607
	bool	ftp_put(csi_t* csi, SOCKET ctrl_sock, char* src, char* dest);
608
609
610
	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*);

611
612
613
	bool	select_shell(void);
	bool	select_editor(void);

614
615
616
	void	sys_info(void);
	void	user_info(void);
	void	xfer_policy(void);
617
618

	void	xfer_prot_menu(enum XFER_TYPE);
619
620
	void	node_stats(uint node_num);
	void	sys_stats(void);
621
	void	logonlist(const char* args = "");
622
	bool	spy(uint node_num);
623
624
625

	void	reset_logon_vars(void);

626
	uint	finduser(const char* str, bool silent_failure = false);
627
628
629
630
631
632
633
634
635
636

	int 	sub_op(uint subnum);

	int		dir_op(uint dirnum);
	int		getuserxfers(int fromuser, int destuser, char *fname);

	void	getmsgptrs(void);
	void	putmsgptrs(void);
	void	getusrsubs(void);
	void	getusrdirs(void);
637
638
	uint	getusrsub(uint subnum);
	uint	getusrgrp(uint subnum);
639
640
	uint	getusrdir(uint dirnum);
	uint	getusrlib(uint dirnum);
641

642
	uint	userdatdupe(uint usernumber, uint offset, uint datlen, char *dat
643
				,bool del=false, bool next=false);
644
	ulong	gettimeleft(bool handle_out_of_time=true);
645
646
647
	bool	gettimeleft_inside;

	/* str.cpp */
648
	char*	server_host_name(void);
649
650
	char*	timestr(time_t);
	char*	datestr(time_t);
651
    char	timestr_output[60];
652
	char	datestr_output[60];
653
	char*	age_of_posted_item(char* buf, size_t max, time_t);
654
	void	userlist(long mode);
655
	size_t	gettmplt(char *outstr, const char *tmplt, long mode);
656
	void	sif(char *fname, char *answers, long len);	/* Synchronet Interface File */
657
658
659
660
	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
661
	bool	inputnstime32(time32_t *dt);
662
	bool	inputnstime(time_t *dt);
663
	bool	chkpass(char *pass, user_t* user, bool unique);
664
	char *	cmdstr(const char *instr, const char *fpath, const char *fspec, char *outstr, long mode = EX_UNSPECIFIED);
665
666
667
668
	char	cmdstr_output[512];

	void	subinfo(uint subnum);
	void	dirinfo(uint dirnum);
669
	bool	trashcan(const char *insearch, const char *name);
670
671
	void	time_bank(void);
	void	change_user(void);
672
673
674

	/* writemsg.cpp */
	void	automsg(void);
675
	bool	writemsg(const char *str, const char *top, char *subj, long mode, uint subnum
676
				,const char *to, const char* from, const char** editor=NULL, const char** charset=NULL);
677
	char*	quotes_fname(int xedit, char* buf, size_t len);
678
	char*	msg_tmp_fname(int xedit, char* fname, size_t len);
679
	char	putmsg(const char *str, long mode, long org_cols = 0, JSObject* obj = NULL);
680
	char	putmsgfrag(const char* str, long* mode, long org_cols = 0, JSObject* obj = NULL);
681
	bool	msgabort(void);
682
683
	bool	email(int usernumber, const char *top = NULL, const char *title = NULL
				, long mode = WM_NONE, smb_t* resmb = NULL, smbmsg_t* remsg = NULL);
684
	bool	forwardmsg(smb_t*, smbmsg_t*, const char* to, const char* subject = NULL, const char* comment = NULL);
685
	void	removeline(char *str, char *str2, char num, char skip);
686
	ulong	msgeditor(char *buf, const char *top, char *title);
687
	bool	editfile(char *path, bool msg=false);
rswindell's avatar
rswindell committed
688
	ushort	chmsgattr(smbmsg_t);
689
	bool	quotemsg(smb_t*, smbmsg_t*, bool tails = false);
690
	bool	editmsg(smb_t*, smbmsg_t*);
691
	void	editor_inf(int xeditnum, const char *to, const char* from, const char *subj, long mode
692
				,uint subnum, const char* tagfile);
693
	bool	copyfattach(uint to, uint from, const char* subj);
694
	bool	movemsg(smbmsg_t* msg, uint subnum);
695
696
	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);
697
	void	editor_info_to_msg(smbmsg_t*, const char* editor, const char* charset);
698
	char	editor_details[128];
699

700
	/* postmsg.cpp */
701
	bool	postmsg(uint subnum, long wm_mode = WM_NONE, smb_t* resmb = NULL, smbmsg_t* remsg = NULL);
702

703
704
705
	/* mail.cpp */
	int		delmail(uint usernumber,int which);
	void	telluser(smbmsg_t* msg);
706
	void	delallmail(uint usernumber, int which, bool permanent=true, long lm_mode = 0);
707
708

	/* getmsg.cpp */
709
	int		loadmsg(smbmsg_t *msg, ulong number);
rswindell's avatar
rswindell committed
710
	void	show_msgattr(smbmsg_t*);
711
	void	show_msghdr(smb_t*, smbmsg_t*, const char *subj = NULL, const char* from = NULL, const char* to = NULL);
rswindell's avatar
rswindell committed
712
713
	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);
714
715
	const char* msghdr_text(const smbmsg_t*, uint index);
	char	msghdr_utf8_text[128];
rswindell's avatar
rswindell committed
716
717
	const char* msghdr_field(const smbmsg_t*, const char* str, char* buf = NULL, bool can_utf8 = false);
	char	msgghdr_field_cp437_str[128];
718
719
720
	ulong	getlastmsg(uint subnum, uint32_t *ptr, time_t *t);
	time_t	getmsgtime(uint subnum, ulong ptr);
	ulong	getmsgnum(uint subnum, time_t t);
721
	void	download_msg_attachments(smb_t*, smbmsg_t*, bool del);
722
723

	/* readmail.cpp */
rswindell's avatar
rswindell committed
724
	void	readmail(uint usernumber, int which, long lm_mode = 0);
725
	bool	readmail_inside;
726
	long	searchmail(mail_t*, long start, long msgss, int which, const char *search, const char* order);
727
728

	/* bulkmail.cpp */
729
730
	bool	bulkmail(uchar *ar);
	int		bulkmailhdr(smb_t*, smbmsg_t*, uint usernum);
731
732

	/* con_out.cpp */
rswindell's avatar
rswindell committed
733
	size_t	bstrlen(const char *str, long mode = 0);
rswindell's avatar
rswindell committed
734
	int		bputs(const char *str, long mode = 0);	/* BBS puts function */
735
	int		rputs(const char *str, size_t len=0);	/* BBS raw puts function */
736
737
738
	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
739
740
741
742
743
#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'
744
745
746
747
748
#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'
749
750
751
752
753
#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'
754
755
#endif
	;
756
	void	backspace(int count=1);			/* Output destructive backspace(s) via outchar */
757
	int		outchar(char ch);				/* Output a char - check echo and emu.  */
758
	int		outchar(enum unicode_codepoint, char cp437_fallback);
759
	int		outchar(enum unicode_codepoint, const char* cp437_fallback = NULL);
rswindell's avatar
rswindell committed
760
	void	inc_row(int count);
761
	void	inc_column(int count);
Rob Swindell's avatar
Rob Swindell committed
762
	void	center(const char *str, unsigned int columns = 0);
rswindell's avatar
rswindell committed
763
	void	wide(const char*);
rswindell's avatar
rswindell committed
764
	void	clearscreen(long term);
765
766
	void	clearline(void);
	void	cleartoeol(void);
rswindell's avatar
rswindell committed
767
	void	cleartoeos(void);
768
769
770
771
772
	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);
773
	bool	cursor_xy(int x, int y);
774
	bool	cursor_getxy(int* x, int* y);
775
776
777
	void	carriage_return(int count=1);
	void	line_feed(int count=1);
	void	newline(int count=1);
778
	long	term_supports(long cmp_flags=0);
779
780
	const char* term_type(long term_supports = -1);
	const char* term_charset(long term_supports = -1);
781
	bool	update_nodeterm(void);
782
	int		backfill(const char* str, float pct, int full_attr, int empty_attr);
783
	void	progress(const char* str, int count, int total, int interval=1);
784
785
	bool	saveline(void);
	bool	restoreline(void);
786
	int		petscii_to_ansibbs(unsigned char);
rswindell's avatar
rswindell committed
787
	size_t	print_utf8_as_cp437(const char*, size_t);
788
789
	int		attr(int);				/* Change text color/attributes */
	void	ctrl_a(char);			/* Performs Ctrl-Ax attribute changes */
rswindell's avatar
rswindell committed
790
	char*	auto_utf8(const char*, long* mode);
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
	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);
806
807

	/* getstr.cpp */
808
	size_t	getstr_offset;
809
	size_t	getstr(char *str, size_t length, long mode, const str_list_t history = NULL);
810
	long	getnum(ulong max, ulong dflt=0);
811
	void	insert_indicator(void);
812
813

	/* getkey.cpp */
814
	char	getkey(long mode); 		/* Waits for a key hit local or remote  */
815
	long	getkeys(const char *str, ulong max, long mode = K_UPPER);
816
	void	ungetkey(char ch, bool insert = false);		/* Places 'ch' into the input buffer    */
rswindell's avatar
rswindell committed
817
	void	ungetstr(const char* str, bool insert = false);
818
	char	question[MAX_TEXTDAT_ITEM_LEN+1];
819
820
	bool	yesno(const char *str, long mode = 0);
	bool	noyes(const char *str, long mode = 0);
rswindell's avatar
rswindell committed
821
	bool	pause_inside;
822
	void	pause(void);
823
824
	const char *	mnestr;
	void	mnemonics(const char *str);
825

rswindell's avatar
rswindell committed
826
	/* inkey.cpp */
827
	int		inkey(long mode, unsigned long timeout=0);
rswindell's avatar
rswindell committed
828
	char	handle_ctrlkey(char ch, long mode=0);
829
830
831
832
833
834
835
836
837

									// 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
838
	long	mouse_mode;			// Mouse reporting mode flags
rswindell's avatar
rswindell committed
839
	uint	hot_attr;			// Auto-Mouse hot-spot attribute (when non-zero)
840
	bool	hungry_hotspots;
rswindell's avatar
rswindell committed
841
	link_list_t mouse_hotspots;	// Mouse hot-spots
842
	struct mouse_hotspot* pause_hotspot;
rswindell's avatar
rswindell committed
843
	struct mouse_hotspot* add_hotspot(struct mouse_hotspot*);
844
845
846
	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
847
848
849
	void	clear_hotspots(void);
	void	scroll_hotspots(long count);
	void	set_mouse(long mode);
rswindell's avatar
rswindell committed
850

851
	/* prntfile.cpp */
852
853
854
	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);
855
	bool	random_menu(const char *code, long mode = 0, JSObject* obj = NULL);
856
	bool	menu_exists(const char *code, const char* ext=NULL, char* realpath=NULL);
857

858
	int		uselect(int add, uint n, const char *title, const char *item, const uchar *ar);
859
860
	uint	uselect_total, uselect_num[500];

861
862
	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);

863
864
865
	void	redrwstr(char *strin, int i, int l, long mode);

	/* atcodes.cpp */
866
867
	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);
868
869

	/* getnode.cpp */
870
871
	int		getsmsg(int usernumber, bool clearline = false);
	int		getnmsg(bool clearline = false);
872
	int		whos_online(bool listself);/* Lists active nodes, returns active nodes */
873
	void	nodelist(void);
874
875
	int		getnodeext(uint number, char * str);
	int		getnodedat(uint number, node_t * node, bool lock);
876
	void	nodesync(bool clearline = false);
877
878
	user_t	nodesync_user;
	bool	nodesync_inside;
879
	uint	count_nodes(bool self = true);
880
881
882
883

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

885
	/* login.ccp */
886
	int		login(char *user_name, char *pw_prompt, const char* user_pw = NULL, const char* sys_pw = NULL);
887
	void	badlogin(char* user, char* passwd, const char* protocol=NULL, xp_sockaddr* addr=NULL, bool delay=true);
888
	char*	parse_login(char*);
889
890

	/* answer.cpp */
891
	bool	answer(void);
892
893

	/* logon.ccp */
894
	bool	logon(void);
895
896

	/* logout.cpp */
897
898
899
	void	logout(void);
	void	backout(void);

900
901
902
	/* newuser.cpp */
	BOOL	newuser(void);					/* Get new user							*/

903
	/* text_sec.cpp */
904
	int		text_sec(void);						/* Text sections */
905
906

	/* readmsgs.cpp */
907
	post_t* loadposts(uint32_t *posts, uint subnum, ulong ptr, long mode, ulong *unvalidated_num, uint32_t* visible=NULL);
908
	int		scanposts(uint subnum, long mode, const char* find);	/* Scan sub-board */
909
	bool	scanposts_inside;
910
	long	listsub(uint subnum, long mode, long start, const char* search);
911
	long	listmsgs(uint subnum, long mode, post_t* post, long start, long posts, bool reading = true);
912
	long	searchposts(uint subnum, post_t* post, long start, long msgs, const char* find);
913
	long	showposts_toyou(uint subnum, post_t* post, ulong start, long posts, long mode=0);
914
	void	show_thread(uint32_t msgnum, post_t* post, unsigned curmsg, int thread_depth = 0, uint64_t reply_mask = 0);
915
	void	dump_msghdr(smbmsg_t*);
rswindell's avatar
rswindell committed
916
	uchar	msg_listing_flag(uint subnum, smbmsg_t*, post_t*);
917
	int64_t get_start_msgnum(smb_t*, int next=0);
918
919
920

	/* chat.cpp */
	void	chatsection(void);
rswindell's avatar
rswindell committed
921
	void	multinodechat(int channel=1);
922
923
	void	nodepage(void);
	void	nodemsg(void);
924
925
	uint	nodemsg_inside;
	uint	hotkey_inside;
926
927
	uchar	lastnodemsg;	/* Number of node last message was sent to */
	char	lastnodemsguser[LEN_ALIAS+1];
928
	void	guruchat(char* line, char* guru, int gurunum, char* last_answer);
929
930
	bool	guruexp(char **ptrptr, char *line);
	void	localguru(char *guru, int gurunum);
rswindell's avatar
rswindell committed
931
932
	bool	sysop_page(void);
	bool	guru_page(void);
933
	void	privchat(bool forced=false, int node_num=0);
934
935
936
937
	bool	chan_access(uint cnum);
	int		getnodetopage(int all, int telegram);

	/* main.cpp */
938
	int		lputs(int level, const char* str);
939
940
941
942
943
	int		lprintf(int level, const char *fmt, ...)
#if defined(__GNUC__)   // Catch printf-format errors
    __attribute__ ((format (printf, 3, 4)));		// 1 is 'this'
#endif
	;
944
945
946
	void	printstatslog(uint node);
	ulong