Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

logfile.cpp 7.79 KB
Newer Older
1 2 3 4 5 6
/* Synchronet log file routines */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
rswindell's avatar
rswindell committed
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
 *																			*
 * 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.	*
 ****************************************************************************/

#include "sbbs.h"
23 24
#include "git_branch.h"
#include "git_hash.h"
25

rswindell's avatar
rswindell committed
26 27
const char* log_line_ending = "\r\n";

Rob Swindell's avatar
Rob Swindell committed
28
extern "C" BOOL hacklog(scfg_t* cfg, const char* prot, const char* user, const char* text, const char* host, union xp_sockaddr* addr)
29
{
30
	char	tstr[64];
31
	char	fname[MAX_PATH+1];
rswindell's avatar
rswindell committed
32
	FILE*	fp;
deuce's avatar
deuce committed
33
	char	ip[INET6_ADDRSTRLEN];
34
	time32_t now=time32(NULL);
35

rswindell's avatar
rswindell committed
36
	SAFEPRINTF(fname, "%shack.log", cfg->logs_dir);
37

rswindell's avatar
rswindell committed
38 39
	if((fp = fnopen(NULL, fname, O_WRONLY|O_CREAT|O_APPEND)) == NULL)
		return false;
40

deuce's avatar
deuce committed
41
	inet_addrtop(addr, ip, sizeof(ip));
rswindell's avatar
rswindell committed
42
	fprintf(fp,"SUSPECTED %s HACK ATTEMPT for user '%s' on %.24s%sUsing port %u at %s [%s]%s"
43 44
		,prot
		,user
45
		,timestr(cfg,now,tstr)
rswindell's avatar
rswindell committed
46
		,log_line_ending
deuce's avatar
deuce committed
47
		,inet_addrport(addr)
48
		,host
deuce's avatar
deuce committed
49
		,ip
rswindell's avatar
rswindell committed
50
		,log_line_ending
51
		);
rswindell's avatar
rswindell committed
52 53 54 55
	if(text != NULL)
		fprintf(fp, "Details: %s%s", text, log_line_ending);
	fputs(log_line_ending, fp);
	fclose(fp);
56

rswindell's avatar
rswindell committed
57
	return true;
58 59
}

Rob Swindell's avatar
Rob Swindell committed
60
BOOL sbbs_t::hacklog(const char* prot, const char* text)
61 62 63 64
{
	return ::hacklog(&cfg, prot, useron.alias, text, client_name, &client_addr);
}

Rob Swindell's avatar
Rob Swindell committed
65
extern "C" BOOL spamlog(scfg_t* cfg, char* prot, char* action
66 67
								,char* reason, char* host, char* ip_addr
								,char* to, char* from)
68
{
69
	char	to_user[256];
70
	char	tstr[64];
71
	char	fname[MAX_PATH+1];
rswindell's avatar
rswindell committed
72
	FILE*	fp;
73
	time32_t now=time32(NULL);
74

rswindell's avatar
rswindell committed
75
	SAFEPRINTF(fname, "%sspam.log", cfg->logs_dir);
76

rswindell's avatar
rswindell committed
77 78
	if((fp = fnopen(NULL, fname, O_WRONLY|O_CREAT|O_APPEND)) == NULL)
		return false;
79

80 81 82
	if(to==NULL)
		to_user[0]=0;
	else
rswindell's avatar
rswindell committed
83
		SAFEPRINTF(to_user,"to: %.128s",to);
84 85 86

	if(from==NULL)
		from=host;
87
		
rswindell's avatar
rswindell committed
88
	fprintf(fp, "SUSPECTED %s SPAM %s on %.24s%sHost: %s [%s]%sFrom: %.128s %s%s"
89
		,prot
90
		,action
91
		,timestr(cfg,now,tstr)
rswindell's avatar
rswindell committed
92
		,log_line_ending
93 94
		,host
		,ip_addr
rswindell's avatar
rswindell committed
95
		,log_line_ending
96
		,from
97
		,to_user
rswindell's avatar
rswindell committed
98
		,log_line_ending
99
		);
rswindell's avatar
rswindell committed
100 101 102 103 104 105
	if(reason != NULL)
		fprintf(fp, "Reason: %s%s", reason, log_line_ending);
	fputs(log_line_ending, fp);
	fclose(fp);

	return true;
106 107
}

Rob Swindell's avatar
Rob Swindell committed
108
extern "C" int errorlog(scfg_t* cfg, int level, const char* host, const char* text)
109 110 111 112
{
	FILE*	fp;
	char	buf[128];
	char	path[MAX_PATH+1];
113
	time_t	now = time(NULL);
114

rswindell's avatar
rswindell committed
115 116
	SAFEPRINTF(path, "%serror.log", cfg->logs_dir);
	if((fp = fnopen(NULL,path,O_WRONLY|O_CREAT|O_APPEND))==NULL)
117
		return -1; 
118
	fprintf(fp,"%.24s %s/%s %s%s%s%s%s"
119
		,ctime_r(&now, buf)
120 121
		,GIT_BRANCH
		,GIT_HASH
rswindell's avatar
rswindell committed
122 123 124 125 126 127
		,host==NULL ? "":host
		,log_line_ending
		,text
		,log_line_ending
		,log_line_ending
		);
128
	fclose(fp);
129
	if(cfg->node_erruser && level <= cfg->node_errlevel) {
130 131 132 133
		char subject[128];
		SAFEPRINTF2(subject, "%s %sERROR occurred", host == NULL ? "" : host, level <= LOG_CRIT ? "CRITICAL " : "");
		notify(cfg, cfg->node_erruser, subject, text);
	}
134 135 136
	return 0;
}

137
void sbbs_t::logentry(const char *code, const char *entry)
138 139 140 141
{
	char str[512];

	now=time(NULL);
rswindell's avatar
rswindell committed
142
	SAFEPRINTF4(str, "Node %2d  %s%s   %s", cfg.node_num, timestr(now), log_line_ending, entry);
143 144 145 146 147 148
	logline(code,str);
}

/****************************************************************************/
/* Writes 'str' verbatim into node.log 										*/
/****************************************************************************/
149
void sbbs_t::log(const char *str)
150 151 152
{
	if(logfile_fp==NULL || online==ON_LOCAL) return;
	if(logcol>=78 || (78-logcol)<strlen(str)) {
rswindell's avatar
rswindell committed
153
		fputs(log_line_ending, logfile_fp);
154 155
		logcol=1; 
	}
156
	if(logcol==1) {
157
		fputs("   ",logfile_fp);
158 159
		logcol=4; 
	}
160
	fputs(str,logfile_fp);
161
	if(*lastchar(str)==LF) {
162
		logcol=1;
163 164
		fflush(logfile_fp);
	}
165 166 167 168 169
	else
		logcol+=strlen(str);
}

/****************************************************************************/
170
/* Writes 'str' on it's own line in node.log (using LOG_INFO level)			*/
171
/****************************************************************************/
172
void sbbs_t::logline(const char *code, const char *str)
173 174 175 176 177 178 179 180
{
	logline(LOG_INFO, code, str);
}

/****************************************************************************/
/* Writes 'str' on it's own line in node.log								*/
/****************************************************************************/
void sbbs_t::logline(int level, const char *code, const char *str)
181
{
182 183
	if(strchr(str,'\n')==NULL) 	// Keep the console log pretty
		lputs(level, str);
184 185
	if(logfile_fp==NULL || (online==ON_LOCAL && strcmp(code,"!!"))) return;
	if(logcol!=1)
rswindell's avatar
rswindell committed
186 187
		fputs(log_line_ending, logfile_fp);
	fprintf(logfile_fp,"%-2.2s %s%s", code, str, log_line_ending);
188
	logcol=1;
189
	fflush(logfile_fp);
190 191 192 193 194
}

/****************************************************************************/
/* Writes a comma then 'ch' to log, tracking column.						*/
/****************************************************************************/
195
void sbbs_t::logch(char ch, bool comma)
196 197 198
{

	if(logfile_fp==NULL || (online==ON_LOCAL)) return;
199
	if((uchar)ch<' ')	/* Don't log control chars */
200 201 202 203 204 205 206
		return;
	if(logcol==1) {
		logcol=4;
		fprintf(logfile_fp,"   "); 
	}
	else if(logcol>=78) {
		logcol=4;
rswindell's avatar
rswindell committed
207
		fprintf(logfile_fp, "%s   ", log_line_ending); 
208 209 210 211 212 213 214
	}
	if(comma && logcol!=4) {
		fprintf(logfile_fp,",");
		logcol++; 
	}
	if(ch&0x80) {
		ch&=0x7f;
215
		if(ch<' ')
216 217 218 219 220 221 222
			return;
		fprintf(logfile_fp,"/"); 
	}
	fprintf(logfile_fp,"%c",ch);
	logcol++;
}

223 224 225 226 227
/****************************************************************************/
/* Error handling routine. Prints to local and remote screens the error     */
/* information, function, action, object and access and then attempts to    */
/* write the error information into the file ERROR.LOG and NODE.LOG         */
/****************************************************************************/
228 229
void sbbs_t::errormsg(int line, const char* function, const char *src, const char* action, const char *object
					  ,long access, const char *extinfo)
230
{
231
    char	str[2048];
232 233
	char	errno_str[128];
	char	errno_info[256] = "";
234 235 236 237 238 239

	/* prevent recursion */
	if(errormsg_inside)
		return;
	errormsg_inside=true;

240 241 242 243 244 245 246 247 248 249 250 251
	if(strcmp(action, ERR_CHK) != 0)
		safe_snprintf(errno_info, sizeof(errno_info), "%d (%s) "
	#ifdef _WIN32
			"(WinError %u) "
	#endif
			,errno, safe_strerror(errno, errno_str, sizeof(errno_str))
	#ifdef _WIN32
			,GetLastError()
	#endif
		);

	safe_snprintf(str,sizeof(str),"ERROR %s"
252
		"in %s line %u (%s) %s \"%s\" access=%ld %s%s"
253
		,errno_info
254
		,src, line, function, action, object, access
255 256
		,extinfo==NULL ? "":"info="
		,extinfo==NULL ? "":extinfo);
257 258 259

	lprintf(LOG_ERR, "!%s", str);
	if(online == ON_REMOTE) {
260 261 262 263 264 265
		int savatr=curatr;
		attr(cfg.color[clr_err]);
		bprintf("\7\r\n!ERROR %s %s\r\n", action, object);   /* tell user about error */
		bputs("\r\nThe sysop has been notified.\r\n");
		pause();
		attr(savatr);
266 267
		CRLF;
	}
268
	safe_snprintf(str,sizeof(str),"ERROR %s %s", action, object);
269 270
	if(cfg.node_num>0) {
		getnodedat(cfg.node_num,&thisnode,1);
271 272 273
		if(thisnode.errors<UCHAR_MAX)
			thisnode.errors++;
		criterrs=thisnode.errors;
274 275 276
		putnodedat(cfg.node_num,&thisnode);
	}
	now=time(NULL);
277

278 279
	if(logfile_fp!=NULL) {
		if(logcol!=1)
rswindell's avatar
rswindell committed
280 281
			fputs(log_line_ending, logfile_fp);
		fprintf(logfile_fp,"!! %s%s", str, log_line_ending);
282 283
		logcol=1;
		fflush(logfile_fp);
284
	}
285

286 287
	errormsg_inside=false;
}