Newer
Older
/* getnode.cpp */
/* Synchronet node information retrieval functions */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
* *
* 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 *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
#include "cmdshell.h"
/****************************************************************************/
/* Reads the data for node number 'number' into the structure 'node' */
/* from NODE.DAB */
/* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
/****************************************************************************/
int sbbs_t::getnodedat(uint number, node_t *node, bool lockit)
char str[MAX_PATH+1];
int rd=sizeof(node_t);
int count;
if(node==NULL || number<1)
return(-1);
errormsg(WHERE,ERR_CHK,"node number",number);
return(-1);
if(node!=&thisnode)
memset(node,0,sizeof(node_t));
sprintf(str,"%snode.dab",cfg.ctrl_dir);
if(nodefile==-1) {
if((nodefile=nopen(str,O_RDWR|O_DENYNONE))==-1) {
errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_DENYNONE);
return(errno);
}
}
else
utime(str,NULL); /* NFS fix... utime() forces a cache refresh */
number--; /* make zero based */
for(count=0;count<LOOP_NODEDAB;count++) {
if(count)
if(lockit && lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))!=0) {
unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
continue;
lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
rd=read(nodefile,node,sizeof(node_t));
if(!lockit || rd!=sizeof(node_t))
unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
if(rd==sizeof(node_t))
}
if(!lockit && cfg.node_misc&NM_CLOSENODEDAB) {
close(nodefile);
nodefile=-1;
}
if(count==LOOP_NODEDAB) {
errormsg(WHERE,rd==sizeof(node_t) ? ERR_LOCK : ERR_READ,"node.dab",number+1);
if(nodefile!=-1)
close(nodefile);
nodefile=-1;
return(-2);
}
if(count>(LOOP_NODEDAB/2)) {
sprintf(str,"NODE.DAB (node %d) COLLISION - Count: %d"
,number+1, count);
logline(LOG_WARNING,"!!",str);
}
return(0);
}
/****************************************************************************/
/* Synchronizes all the nodes knowledge of the other nodes' actions, mode, */
/* status and other flags. */
/* Assumes that getnodedat(node_num,&thisnode,0) was called right before it */
/* is called. */
/****************************************************************************/
void sbbs_t::nodesync()
{
char str[256],today[32];
nodesync_inside=1;
if(thisnode.action!=action) {
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.action=action;
putnodedat(cfg.node_num,&thisnode);
}
criterrs=thisnode.errors;
if(sys_status&SS_USERON) {
if(thisnode.status==NODE_WFC) {
lprintf(LOG_ERR, "Node %d NODE STATUS FIXUP", cfg.node_num);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.status=NODE_INUSE;
thisnode.useron=useron.number;
putnodedat(cfg.node_num,&thisnode);
}
if(!(sys_status&SS_NEWDAY)) {
now=time(NULL);
unixtodstr(&cfg,(time32_t)logontime,str);
unixtodstr(&cfg,(time32_t)now,today);
if(strcmp(str,today)) { /* New day, clear "today" user vars */
sys_status|=SS_NEWDAY; // So we don't keep doing this over&over
resetdailyuserdat(&cfg, &useron,/* write: */true);

rswindell
committed
}
}
if(thisnode.misc&NODE_UDAT && !(useron.rest&FLAG('G'))) { /* not guest */
getuserdat(&cfg, &useron);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc&=~NODE_UDAT;
putnodedat(cfg.node_num,&thisnode);
}
if(!(sys_status&SS_MOFF)) {
if(thisnode.misc&NODE_MSGW)
getsmsg(useron.number); /* getsmsg clears MSGW flag */
if(thisnode.misc&NODE_NMSG)
getnmsg(); /* getnmsg clears NMSG flag */
}
if(cfg.sync_mod[0])
exec_bin(cfg.sync_mod,&main_csi);
if(thisnode.misc&NODE_INTR) {
bputs(text[NodeLocked]);
logline(LOG_NOTICE,nulstr,"Interrupted");
hangup();
nodesync_inside=0;
return;
}
if(thisnode.misc&NODE_LCHAT) { // pulled into local chat with sysop
SAVELINE;
privchat(true);
RESTORELINE;
}
if(sys_status&SS_USERON && memcmp(&nodesync_user,&useron,sizeof(user_t))) {
getusrdirs();
getusrsubs();
memcpy(&nodesync_user,&useron,sizeof(nodesync_user));
}
if(sys_status&SS_USERON && online && (timeleft/60)<(5-timeleft_warn)
&& !SYSOP) {
timeleft_warn=5-(timeleft/60);
if(!(sys_status&SS_MOFF)) {
attr(LIGHTGRAY);
bprintf(text[OnlyXminutesLeft]
,((ushort)timeleft/60)+1,(timeleft/60) ? "s" : nulstr);
}
attr(atr); /* replace original attributes */
nodesync_inside=0;
}
/****************************************************************************/
/* Prints short messages waiting for this node, if any... */
/****************************************************************************/
int sbbs_t::getnmsg()
int file;
long length;
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc&=~NODE_NMSG; /* clear the NMSG flag */
putnodedat(cfg.node_num,&thisnode);
}

rswindell
committed
sprintf(str,"%smsgs/n%3.3u.msg",cfg.data_dir,cfg.node_num);
return(0);
if((file=nopen(str,O_RDWR))==-1) {
/**
errormsg(WHERE,ERR_OPEN,str,O_RDWR);
**/
return(errno);
length=(long)filelength(file);
if(!length) {
close(file);
return(0);
}
close(file);
errormsg(WHERE,ERR_ALLOC,str,length+1);
return(-1);
}
if(lread(file,buf,length)!=length) {
close(file);
errormsg(WHERE,ERR_READ,str,length);
return(errno);
}
chsize(file,0L);
close(file);
buf[length]=0;
if(thisnode.action==NODE_MAIN || thisnode.action==NODE_XFER
|| sys_status&SS_IN_CTRLP) {
CRLF;
}
return(0);
}
/****************************************************************************/
/* 'ext' must be at least 128 bytes! */
/****************************************************************************/
int sbbs_t::getnodeext(uint number, char *ext)
char str[MAX_PATH+1];
int rd,count;
if(!number || number>cfg.sys_nodes) {
errormsg(WHERE,ERR_CHK,"node number",number);
return(-1);
sprintf(str,"%snode.exb",cfg.ctrl_dir);
if((node_ext=nopen(str,O_RDONLY|O_DENYNONE))==-1) {
memset(ext,0,128);
errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_DENYNONE);
return(errno);
}
number--; /* make zero based */
for(count=0;count<LOOP_NODEDAB;count++) {
if(count)
if(lock(node_ext,(long)number*128L,128)!=0)
lseek(node_ext,(long)number*128L,SEEK_SET);
rd=read(node_ext,ext,128);
unlock(node_ext,(long)number*128L,128);
if(rd==128)
close(node_ext);
node_ext=-1;
if(count==LOOP_NODEDAB) {
errormsg(WHERE,ERR_READ,"node.exb",number+1);
return(-2);
}
if(count>(LOOP_NODEDAB/2)) {
sprintf(str,"NODE.EXB (node %d) COLLISION - Count: %d"
,number+1, count);
logline("!!",str);
}
return(0);
}
/****************************************************************************/
/* Prints short messages waiting for 'usernumber', if any... */
/* then deletes them. */
/****************************************************************************/
int sbbs_t::getsmsg(int usernumber)
int file;
long length;
node_t node;
int i;
for(i=1;i<=cfg.sys_nodes;i++) { /* clear msg waiting flag */
if(getnodedat(i,&node,true)==0) {
if(node.useron==usernumber
&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
&& node.misc&NODE_MSGW)
node.misc&=~NODE_MSGW;
putnodedat(i,&node);
}
}

rswindell
committed
sprintf(str,"%smsgs/%4.4u.msg",cfg.data_dir,usernumber);
return(0);
if((file=nopen(str,O_RDWR))==-1) {
errormsg(WHERE,ERR_OPEN,str,O_RDWR);
return(errno);
}
length=(long)filelength(file);
close(file);
errormsg(WHERE,ERR_ALLOC,str,length+1);
return(-1);
}
if(lread(file,buf,length)!=length) {
close(file);
errormsg(WHERE,ERR_READ,str,length);
return(errno);
}
chsize(file,0L);
close(file);
buf[length]=0;
getnodedat(cfg.node_num,&thisnode,0);
if(thisnode.action==NODE_MAIN || thisnode.action==NODE_XFER
|| sys_status&SS_IN_CTRLP) {
CRLF;
}
return(0);
}
/****************************************************************************/
/* This function lists users that are online. */
/* If listself is true, it will list the current node. */
/* Returns number of active nodes (not including current node). */
/****************************************************************************/
int sbbs_t::whos_online(bool listself)
{
int i,j;
node_t node;
CRLF;
bputs(text[NodeLstHdr]);
for(j=0,i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
getnodedat(i,&node,0);
if(i==cfg.node_num) {
if(listself)
printnodedat(i,&node);
continue;
}
if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
printnodedat(i,&node);
if(!lastnodemsg)
lastnodemsg=i;
j++;
}
}
if(!j)
bputs(text[NoOtherActiveNodes]);
return(j);
}
void sbbs_t::nodelist(void)
{
node_t node;
CRLF;
bputs(text[NodeLstHdr]);
for(int i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
getnodedat(i,&node,0);
printnodedat(i,&node);
}
}
static char* node_connection_desc(sbbs_t* sbbs, ushort conn, char* str)
{
switch(conn) {
case NODE_CONNECTION_LOCAL:
case NODE_CONNECTION_TELNET:
return sbbs->text[NodeConnectionTelnet];
case NODE_CONNECTION_RLOGIN:
return sbbs->text[NodeConnectionRLogin];
case NODE_CONNECTION_SSH:
return sbbs->text[NodeConnectionSSH];
default:
sprintf(str,sbbs->text[NodeConnectionModem],conn);
break;
}
return str;
}
/****************************************************************************/
/* Displays the information for node number 'number' contained in 'node' */
/****************************************************************************/
void sbbs_t::printnodedat(uint number, node_t* node)
{
uint i;
char hour,mer[3];
char tmp[512];
attr(cfg.color[clr_nodenum]);
bprintf("%3d ",number);
attr(cfg.color[clr_nodestatus]);
switch(node->status) {
case NODE_WFC:
bputs(text[NodeStatusWaitingForCall]);
bputs(text[NodeStatusOffline]);
bputs("Networking"); /* obsolete */
bputs(text[NodeStatusLogon]);
bputs(node_connection_desc(this, node->connection, tmp));
case NODE_LOGOUT:
bprintf(text[NodeStatusLogout]
,(node->misc&NODE_ANON) && !SYSOP ? text[UNKNOWN_USER] : username(&cfg,node->useron,tmp));
break;
bputs(text[NodeStatusEventWaiting]);
break;
case NODE_EVENT_LIMBO:
bprintf(text[NodeStatusEventLimbo],node->aux);
break;
case NODE_EVENT_RUNNING:
bputs(text[NodeStatusEventRunning]);
bputs(text[NodeStatusNewUser]);
bputs(node_connection_desc(this, node->connection, tmp));
break;
case NODE_QUIET:
if(!SYSOP) {
bputs(text[NodeStatusWaitingForCall]);
break;
}
case NODE_INUSE:
if(node->misc&NODE_EXT) {
getnodeext(number,tmp);
bputs(tmp);
break;
}
attr(cfg.color[clr_nodeuser]);
if(node->misc&NODE_ANON && !SYSOP)
bputs(text[UNKNOWN_USER]);
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
else
bputs(username(&cfg,node->useron,tmp));
attr(cfg.color[clr_nodestatus]);
bputs(" ");
switch(node->action) {
case NODE_MAIN:
bputs("at main menu");
break;
case NODE_RMSG:
bputs("reading messages");
break;
case NODE_RMAL:
bputs("reading mail");
break;
case NODE_RSML:
bputs("reading sent mail");
break;
case NODE_RTXT:
bputs("reading text files");
break;
case NODE_PMSG:
bputs("posting message");
break;
case NODE_SMAL:
bputs("sending mail");
break;
case NODE_AMSG:
bputs("posting auto-message");
break;
case NODE_XTRN:
if(node->aux<1 || node->aux>cfg.total_xtrns)
bputs("at external program menu");
else {
bputs("running ");
i=node->aux-1;
bputs(cfg.xtrn[node->aux-1]->name);
else
bputs("external program");
}
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
break;
case NODE_DFLT:
bputs("changing defaults");
break;
case NODE_XFER:
bputs("at transfer menu");
break;
case NODE_RFSD:
bprintf("retrieving from device #%d",node->aux);
break;
case NODE_DLNG:
bprintf("downloading");
break;
case NODE_ULNG:
bputs("uploading");
break;
case NODE_BXFR:
bputs("transferring bidirectional");
break;
case NODE_LFIL:
bputs("listing files");
break;
case NODE_LOGN:
bputs("logging on");
break;
case NODE_LCHT:
bprintf("in local chat with %s",cfg.sys_op);
break;
case NODE_MCHT:
if(node->aux) {
bprintf("in multinode chat channel %d",node->aux&0xff);
if(node->aux&0x1f00) { /* password */
outchar('*');
if(SYSOP)
bprintf(" %s",unpackchatpass(tmp,node));
}
}
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
else
bputs("in multinode global chat channel");
break;
case NODE_PAGE:
bprintf("paging node %u for private chat",node->aux);
break;
case NODE_PCHT:
if(node->aux)
bprintf("in private chat with node %u",node->aux);
else
bprintf("in local chat with %s",cfg.sys_op);
break;
case NODE_GCHT:
i=node->aux;
if(i>=cfg.total_gurus)
i=0;
bprintf("chatting with %s",cfg.guru[i]->name);
break;
case NODE_CHAT:
bputs("in chat section");
break;
case NODE_TQWK:
bputs("transferring QWK packet");
break;
case NODE_SYSP:
bputs("performing sysop activities");
break;
default:
bputs(node_connection_desc(this, node->connection, tmp));
if(node->action==NODE_DLNG) {
if(cfg.sys_misc&SM_MILITARY) {
hour=node->aux/60;
mer[0]=0;
}
else if((node->aux/60)>=12) {
if(node->aux/60==12)
hour=12;
else
hour=(node->aux/60)-12;
strcpy(mer,"pm");
}
else {
if((node->aux/60)==0) /* 12 midnite */
hour=12;
else hour=node->aux/60;
strcpy(mer,"am");
}
,hour,node->aux%60,mer);
}
break;
}
i=NODE_LOCK;
if(node->status==NODE_INUSE || SYSOP)
i|=NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG;
if(node->misc&i) {
bputs(" (");
if(node->misc&(i&NODE_AOFF))
outchar('A');
if(node->misc&NODE_LOCK)
outchar('L');
if(node->misc&(i&(NODE_MSGW|NODE_NMSG)))
outchar('M');
if(node->misc&(i&NODE_POFF))
outchar('P');
outchar(')');
}
if(SYSOP && ((node->misc
&(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN|NODE_LCHAT))
|| node->status==NODE_QUIET)) {
bputs(" [");
if(node->misc&NODE_ANON)
outchar('A');
if(node->misc&NODE_INTR)
outchar('I');
if(node->misc&NODE_RRUN)
outchar('R');
if(node->misc&NODE_UDAT)
outchar('U');
if(node->status==NODE_QUIET)
outchar('Q');
if(node->misc&NODE_EVENT)
outchar('E');
if(node->misc&NODE_DOWN)
outchar('D');
if(node->misc&NODE_LCHAT)
outchar('C');
outchar(']');
}
if(node->errors && SYSOP) {
attr(cfg.color[clr_err]);
bprintf(" %d error%c",node->errors, node->errors>1 ? 's' : '\0' );
}
attr(LIGHTGRAY);
CRLF;
}