Skip to content
Snippets Groups Projects
logout.cpp 6.45 KiB
Newer Older
/* Synchronet user logout 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
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
 *																			*
 * 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"
#include "cmdshell.h"

/****************************************************************************/
/* Function that is called after a user hangs up or logs off				*/
/****************************************************************************/
void sbbs_t::logout()
{
	char	str[256];
	int 	i,j;
	ushort	ttoday;
	node_t	node;
		errormsg(WHERE,ERR_CHK,"localtime",(ulong)now);

	if(!useron.number) {				 /* Not logged in, so do nothing */
		if(!online) {
				,(uint)(now-answertime));
	lprintf(LOG_INFO, "logout initiated");
	SAFECOPY(lastuseron,useron.alias); // TODO: race condition here
	if(!online && getnodedat(cfg.node_num, &node, /* lock: */true) == 0) {
		node.status = NODE_LOGOUT;
		putnodedat(cfg.node_num, &node);
	}
rswindell's avatar
rswindell committed
	if(useron.rest&FLAG('G')) {
		putuserstr(useron.number, USER_NAME, nulstr);
rswindell's avatar
rswindell committed
	}

	if(sys_status&SS_USERON && thisnode.status!=NODE_QUIET && !(useron.rest&FLAG('Q')))
		for(i=1;i<=cfg.sys_nodes;i++)
			if(i!=cfg.node_num) {
				getnodedat(i,&node,0);
				if((node.status==NODE_INUSE || node.status==NODE_QUIET)
					&& !(node.misc&NODE_AOFF) && node.useron!=useron.number) {
					SAFEPRINTF2(str,text[NodeLoggedOff],cfg.node_num
						,thisnode.misc&NODE_ANON
						? text[UNKNOWN_USER] : useron.alias);

	if(!online) {		/* NOT re-login */
		if(cfg.sys_logout[0]) {		/* execute system logout event */
			lprintf(LOG_DEBUG, "executing logout event: %s", cfg.sys_logout);
			external(cmdstr(cfg.sys_logout,nulstr,nulstr,NULL),EX_OUTL|EX_OFFLINE);
		lprintf(LOG_DEBUG, "executing logout module: %s", cfg.logout_mod);
		exec_bin(cfg.logout_mod,&main_csi);
	}
	SAFEPRINTF2(path,"%smsgs/%4.4u.msg",cfg.data_dir,useron.number);
	if(fexistcase(path) && !flength(path))		/* remove any 0 byte message files */
		remove(path);
	if(sys_status&SS_USERON) {	// Insures the useron actually went through logon()/getmsgptrs() first
	if(!REALSYSOP)
		logofflist();

	ttoday=useron.ttoday-useron.textra; 		/* billable time used prev calls */
	if(ttoday>=cfg.level_timeperday[useron.level])
		i=0;
	else
		i=cfg.level_timeperday[useron.level]-ttoday;
	if(i>cfg.level_timepercall[useron.level])      /* i=amount of time without min */
		i=cfg.level_timepercall[useron.level];
	j=(int)(now-starttime)/60;			/* j=billable time online in min */
	if(i<0) i=0;
	if(j<0) j=0;

	if(useron.min && j>i) {
		j-=i;                               /* j=time to deduct from min */
		SAFEPRINTF(str,"Minute Adjustment: %d",-j);
		logline(">>",str);
		if(useron.min>(ulong)j)
			useron.min-=j;
		else
			useron.min=0L;
		putuserdec32(useron.number, USER_MIN, useron.min); 

	if(timeleft>0 && starttime-logontime>0) 			/* extra time */
		useron.textra+=(ushort)((starttime-logontime)/60);
	putuserdec32(useron.number, USER_TEXTRA, useron.textra);
	putuserdatetime(useron.number, USER_NS_TIME, last_ns_time);
	logoutuserdat(&cfg, &useron, now, logontime);

	getusrsubs();
	getusrdirs();
	if(usrgrps>0)
		putuserstr(useron.number, USER_CURSUB, cfg.sub[usrsub[curgrp][cursub[curgrp]]]->code);
		putuserstr(useron.number, USER_CURDIR, cfg.dir[usrdir[curlib][curdir[curlib]]]->code);
	SAFECAT(str,"  ");
	if(sys_status&SS_USERON) {
		char ulb[64];
		char dlb[64];
		safe_snprintf(tmp,sizeof(tmp),"T:%3u   R:%3u   P:%3u   E:%3u   F:%3u   "
			"U:%4s %u   D:%4s %u"
			,(uint)(now-logontime)/60,posts_read,logon_posts
			,logon_emails,logon_fbacks
			,byte_estimate_to_str(logon_ulb, ulb, sizeof(ulb), 1024, /* precision: */logon_ulb > 1024*1024)
			,logon_uls
			,byte_estimate_to_str(logon_dlb, dlb, sizeof(dlb), 1024, /* precision: */logon_dlb > 1024*1204)
			,logon_dls);
	} else
		SAFEPRINTF(tmp,"T:%3u sec",(uint)(now-answertime));
	SAFECAT(str,tmp);
	SAFECAT(str,"\r\n");
	logline("@-",str);
	sys_status&=~SS_USERON;
	answertime=now; // In case we're re-logging on
	if(startup->sound.logout[0] && !sound_muted(&cfg))
		PlaySound(startup->sound.logout, NULL, SND_ASYNC|SND_FILENAME);
#endif

	mqtt_user_logout(mqtt, &client, logontime);

	lprintf(LOG_DEBUG, "logout completed");
}

/****************************************************************************/
/* Detailed usage stats for each logon                                      */
/****************************************************************************/
bool sbbs_t::logofflist()
{
    char str[256];
    int file;
	if(localtime_r(&logontime,&tm)==NULL)
	SAFEPRINTF4(str,"%slogs/%2.2d%2.2d%2.2d.lol",cfg.logs_dir,tm.tm_mon+1,tm.tm_mday
	if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
	safe_snprintf(str,sizeof(str),"%-*.*s %-2u %-8.8s %2.2u:%2.2u %2.2u:%2.2u %3u %2u %2u %2u %2u "
		"%2u %2u\r\n",LEN_ALIAS,LEN_ALIAS,useron.alias,cfg.node_num,connection
		,tm.tm_hour,tm.tm_min,tm_now.tm_hour,tm_now.tm_min
		,(int)(now-logontime)/60,posts_read,logon_posts,logon_emails
		,logon_fbacks,logon_uls,logon_dls);
	int wr = write(file,str,strlen(str));
	return wr == strlen(str);