Newer
Older
if(!VALID_CFG(cfg) || birth==NULL)
return(0);
if(!atoi(birth) || !atoi(birth+3)) /* Invalid */
return(0);
now=time(NULL);
if(localtime_r(&now,&tm)==NULL)
tm.tm_mon++; /* convert to 1 based */
int year = getbirthyear(birth);
int age = (1900 + tm.tm_year) - year;
int mon = getbirthmonth(cfg, birth);
int day = getbirthday(cfg, birth);
if(mon < 1 || mon > 12 || day < 1 || day > 31)
return 0;
if(mon > tm.tm_mon || (mon == tm.tm_mon && day > tm.tm_mday))
age--;
return age;
/****************************************************************************/
/* Converts from MM/DD/YYYYY, DD/MM/YYYY, or YYYY/MM/DD to YYYYMMDD */
/****************************************************************************/
char* parse_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t maxlen)
{
if (cfg->sys_date_fmt == YYMMDD)
safe_snprintf(out, maxlen, "%.4s%.2s%.2s", birthdate, birthdate + 5, birthdate + 8);
else if (cfg->sys_date_fmt == DDMMYY)
safe_snprintf(out, maxlen, "%.4s%.2s%.2s", birthdate + 6, birthdate + 3, birthdate);
else
safe_snprintf(out, maxlen, "%.4s%.2s%.2s", birthdate + 6, birthdate, birthdate + 3);
return out;
}
/****************************************************************************/
/* Converts from user birth date to MM/DD/YYYYY, DD/MM/YYYY, or YYYY/MM/DD */
/****************************************************************************/
char* format_birthdate(scfg_t* cfg, const char* birthdate, char* out, size_t maxlen)
{
if(maxlen < 1)
return NULL;
*out = '\0';
if(*birthdate) {
if (cfg->sys_date_fmt == YYMMDD)
safe_snprintf(out, maxlen, "%04u%c%02u%c%02u"
, getbirthyear(birthdate)
, cfg->sys_date_sep
, getbirthmonth(cfg, birthdate)
, cfg->sys_date_sep
, getbirthday(cfg, birthdate));
else if (cfg->sys_date_fmt == DDMMYY)
safe_snprintf(out, maxlen, "%02u%c%02u%c%04u"
, getbirthday(cfg, birthdate)
, cfg->sys_date_sep
, getbirthmonth(cfg, birthdate)
, cfg->sys_date_sep
, getbirthyear(birthdate));
safe_snprintf(out, maxlen, "%02u%c%02u%c%04u"
, getbirthmonth(cfg, birthdate)
, cfg->sys_date_sep
, getbirthday(cfg, birthdate)
, cfg->sys_date_sep
, getbirthyear(birthdate));
}
return out;
}
/****************************************************************************/
/****************************************************************************/
char* birthdate_format(scfg_t* cfg, char* buf, size_t size)
switch (cfg->sys_date_fmt) {
case MMDDYY: snprintf(buf, size, "MM%cDD%cYYYY", cfg->sys_date_sep, cfg->sys_date_sep); return buf;
case DDMMYY: snprintf(buf, size, "DD%cMM%cYYYY", cfg->sys_date_sep, cfg->sys_date_sep); return buf;
case YYMMDD: snprintf(buf, size, "YYYY%cMM%cDD", cfg->sys_date_sep, cfg->sys_date_sep); return buf;
}
return "??????????";
/****************************************************************************/
/****************************************************************************/
char* birthdate_template(scfg_t* cfg, char* buf, size_t size)
{
if (cfg->sys_date_fmt == YYMMDD)
snprintf(buf, size, "nnnn%cnn%cnn", cfg->sys_date_sep, cfg->sys_date_sep);
else
snprintf(buf, size, "nn%cnn%cnnnn", cfg->sys_date_sep, cfg->sys_date_sep);
return buf;
}
/****************************************************************************/
/****************************************************************************/
int opennodedat(scfg_t* cfg)
{
char fname[MAX_PATH+1];
if(!VALID_CFG(cfg))
return -1;
SAFEPRINTF(fname, "%snode.dab", cfg->ctrl_dir);
return nopen(fname, O_RDWR|O_DENYNONE);
}
/****************************************************************************/
/****************************************************************************/
int opennodeext(scfg_t* cfg)
{
char fname[MAX_PATH+1];
if(!VALID_CFG(cfg))
return -1;
SAFEPRINTF(fname, "%snode.exb", cfg->ctrl_dir);
return nopen(fname, O_RDWR|O_DENYNONE);
}
/****************************************************************************/

Rob Swindell
committed
/* Reads the data for 1-based node number 'number' into the node structure */

rswindell
committed
/* from node.dab */
/****************************************************************************/
int getnodedat(scfg_t* cfg, uint number, node_t *node, bool lockit, int* fdp)
int rd;
|| node==NULL || number<1 || number>cfg->sys_nodes)
memset(node,0,sizeof(node_t));
if(fdp != NULL && *fdp > 0)
file = *fdp;
else {
if((file = opennodedat(cfg)) == -1)
return errno;
}
if(filelength(file)>=(long)(number*sizeof(node_t))) {
number--; /* make zero based */
for(count=0;count<LOOP_NODEDAB;count++) {
if(count)
mswait(100);
(void)lseek(file,(long)number*sizeof(node_t),SEEK_SET);
if(lockit
&& lock(file,(long)number*sizeof(node_t),sizeof(node_t))!=0)
continue;
rd=read(file,node,sizeof(node_t));
if(rd!=sizeof(node_t))
unlock(file,(long)number*sizeof(node_t),sizeof(node_t));
if(rd==sizeof(node_t))
break;
}
if(fdp==NULL || count==LOOP_NODEDAB)
CLOSE_OPEN_FILE(file);
if(fdp!=NULL)
*fdp=file;
if(count==LOOP_NODEDAB)
return(-2);
return(0);
}
/****************************************************************************/

rswindell
committed
/* Write the data from the structure 'node' into node.dab */

Rob Swindell
committed
/* number is the 1-based node number */
/****************************************************************************/
int putnodedat(scfg_t* cfg, uint number, node_t* node, bool closeit, int file)
size_t wr=0;
int wrerr=0;
if(file<0)
return -1;
|| node==NULL || number<1 || number>cfg->sys_nodes) {
if(closeit)
close(file);
}
number--; /* make zero based */
for(attempts=0;attempts<LOOP_USERDAT;attempts++) {
(void)lseek(file,(long)number*sizeof(node_t),SEEK_SET);
if((wr=write(file,node,sizeof(node_t)))==sizeof(node_t))
break;
wrerr=errno; /* save write error */
mswait(((attempts + 1) / 10) * 100);
}
unlock(file,(long)number*sizeof(node_t),sizeof(node_t));
if(closeit)
close(file);
if(wr!=sizeof(node_t))
return(wrerr);
/****************************************************************************/
/****************************************************************************/
bool set_node_status(scfg_t* cfg, int nodenum, enum node_status status)
{
node_t node;
if(getnodedat(cfg, nodenum, &node, /* lockit: */true, &file) != 0)
return false;
node.status = status;
return putnodedat(cfg, nodenum, &node, /* closeit: */true, file) == 0;
}
/****************************************************************************/
/****************************************************************************/
bool set_node_misc(scfg_t* cfg, int nodenum, uint misc)
{
node_t node;
if(getnodedat(cfg, nodenum, &node, /* lockit: */true, &file) != 0)
return false;
node.misc = misc;
return putnodedat(cfg, nodenum, &node, /* closeit: */true, file) == 0;
}
/****************************************************************************/
/****************************************************************************/
bool set_node_lock(scfg_t* cfg, int nodenum, bool set)
{
node_t node;
if(getnodedat(cfg, nodenum, &node, /* lockit: */true, &file) != 0)
return false;
if(set)
node.misc |= NODE_LOCK;
else
node.misc &= ~NODE_LOCK;
return putnodedat(cfg, nodenum, &node, /* closeit: */true, file) == 0;
}
/****************************************************************************/
/****************************************************************************/
bool set_node_interrupt(scfg_t* cfg, int nodenum, bool set)
{
node_t node;
if(getnodedat(cfg, nodenum, &node, /* lockit: */true, &file) != 0)
return false;
if(set)
node.misc |= NODE_INTR;
else
node.misc &= ~NODE_INTR;
return putnodedat(cfg, nodenum, &node, /* closeit: */true, file) == 0;
}
/****************************************************************************/
/****************************************************************************/
bool set_node_down(scfg_t* cfg, int nodenum, bool set)
{
node_t node;
if(getnodedat(cfg, nodenum, &node, /* lockit: */true, &file) != 0)
return false;
if(set)
node.misc |= NODE_DOWN;
else
node.misc &= ~NODE_DOWN;
return putnodedat(cfg, nodenum, &node, /* closeit: */true, file) == 0;
}
/****************************************************************************/
/****************************************************************************/
bool set_node_rerun(scfg_t* cfg, int nodenum, bool set)
{
node_t node;
if(getnodedat(cfg, nodenum, &node, /* lockit: */true, &file) != 0)
return false;
if(set)
node.misc |= NODE_RRUN;
else
node.misc &= ~NODE_RRUN;
return putnodedat(cfg, nodenum, &node, /* closeit: */true, file) == 0;
}
/****************************************************************************/
/****************************************************************************/
bool set_node_errors(scfg_t* cfg, int nodenum, uint errors)
{
node_t node;
if(getnodedat(cfg, nodenum, &node, /* lockit: */true, &file) != 0)
return false;
node.errors = errors;
return putnodedat(cfg, nodenum, &node, /* closeit: */true, file) == 0;
}
/****************************************************************************/
/* Packs the password 'pass' into 5bit ASCII inside node_t. 32bits in */
/* node.extaux, and the other 8bits in the upper byte of node.aux */
/****************************************************************************/
void packchatpass(char *pass, node_t *node)
{
char bits;
int i,j;
if(pass==NULL || node==NULL)
return;
node->aux&=~0xff00; /* clear the password */
node->extaux=0L;
if((j=strlen(pass))==0) /* there isn't a password */
return;
node->aux|=(int)((pass[0]-64)<<8); /* 1st char goes in low 5bits of aux */
if(j==1) /* password is only one char, we're done */
return;
node->aux|=(int)((pass[1]-64)<<13); /* low 3bits of 2nd char go in aux */
node->extaux|=(long)((pass[1]-64)>>3); /* high 2bits of 2nd char go extaux */
bits=2;
for(i=2;i<j;i++) { /* now process the 3rd char through the last */
node->extaux|=(long)((long)(pass[i]-64)<<bits);
}
}
/****************************************************************************/
/* Unpacks the password 'pass' from the 5bit ASCII inside node_t. 32bits in */
/* node.extaux, and the other 8bits in the upper byte of node.aux */
/****************************************************************************/
char* unpackchatpass(char *pass, node_t* node)
{
char bits;
int i;
if(pass==NULL || node==NULL)
return(NULL);
pass[0]=(node->aux&0x1f00)>>8;
pass[1]=(char)(((node->aux&0xe000)>>13)|((node->extaux&0x3)<<3));
bits=2;
for(i=2;i<8;i++) {
pass[i]=(char)((node->extaux>>bits)&0x1f);
}
pass[8]=0;
for(i=0;i<8;i++)
if(pass[i])
pass[i]+=64;
return(pass);
}
static char* node_connection_desc(ushort conn, char* str)
{
switch(conn) {
case NODE_CONNECTION_LOCAL:
strcpy(str,"Locally");
break;
case NODE_CONNECTION_TELNET:
strcpy(str,"via telnet");
break;
case NODE_CONNECTION_RLOGIN:
strcpy(str,"via rlogin");
break;
case NODE_CONNECTION_SSH:
strcpy(str,"via ssh");
break;

Rob Swindell
committed
case NODE_CONNECTION_SFTP:
strcpy(str,"via sftp");
break;
case NODE_CONNECTION_RAW:
strcpy(str,"via raw");
break;
default:
sprintf(str,"at %ubps",conn);
break;
}
return str;
}
char* getnodeext(scfg_t* cfg, int num, char* buf)
{
int f;
if(!VALID_CFG(cfg) || num < 1)
return "";
if((f = opennodeext(cfg)) < 0)
(void)lseek(f, (num-1) * 128, SEEK_SET);
if(read(f, buf, 128) != 128)
memset(buf, 0, 128);
close(f);
buf[127] = 0;
return buf;
}
char* nodestatus(scfg_t* cfg, node_t* node, char* buf, size_t buflen, int num)
char str[256];
char tmp[128];
char* mer;
int hour;

Rob Swindell
committed
int xtrnnum;
user_t user = {0};
strncpy(buf,"(null)",buflen);
return(buf);
str[0]=0;
switch(node->status) {
case NODE_WFC:
SAFECOPY(str,"Waiting for connection");
break;
case NODE_OFFLINE:
strcpy(str,"Offline");
break;
case NODE_NETTING: /* Obsolete */
SAFECOPY(str,"Networking");
break;
case NODE_LOGON:
SAFEPRINTF(str,"At login prompt %s"
,node_connection_desc(node->connection, tmp));
break;
case NODE_LOGOUT:
SAFEPRINTF(str,"Logging out %s", username(cfg,node->useron,tmp));
break;
case NODE_EVENT_WAITING:
SAFECOPY(str,"Waiting for all nodes to become inactive");
break;
case NODE_EVENT_LIMBO:
SAFEPRINTF(str,"Waiting for node %d to finish external event"
,node->aux);
break;
case NODE_EVENT_RUNNING:
SAFECOPY(str,"Running external event");
break;
case NODE_NEWUSER:
SAFEPRINTF(str,"New user applying for access %s"
,node_connection_desc(node->connection, tmp));
break;
case NODE_QUIET:
case NODE_INUSE:
if(node->misc & NODE_EXT) {
getnodeext(cfg, num, str);
break;
}
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
username(cfg,node->useron,str);
strcat(str," ");
switch(node->action) {
case NODE_MAIN:
strcat(str,"at main menu");
break;
case NODE_RMSG:
strcat(str,"reading messages");
break;
case NODE_RMAL:
strcat(str,"reading mail");
break;
case NODE_RSML:
strcat(str,"reading sent mail");
break;
case NODE_RTXT:
strcat(str,"reading text files");
break;
case NODE_PMSG:
strcat(str,"posting message");
break;
case NODE_SMAL:
strcat(str,"sending mail");
break;
case NODE_AMSG:
strcat(str,"posting auto-message");
break;
case NODE_XTRN:

Rob Swindell
committed
if(node->aux == 0) {
strcat(str,"at external program menu");

Rob Swindell
committed
break;
}
user.number = node->useron;
getuserdat(cfg, &user);
xtrnnum = getxtrnnum(cfg, user.curxtrn);
if(is_valid_xtrnnum(cfg, xtrnnum))
sprintf(str+strlen(str),"running %s"
,cfg->xtrn[xtrnnum]->name);
else if(*user.curxtrn != '\0')
sprintf(str+strlen(str),"running external program %s"
,user.curxtrn);

Rob Swindell
committed
else
sprintf(str+strlen(str),"running external program #%d"
,node->aux);
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
break;
case NODE_DFLT:
strcat(str,"changing defaults");
break;
case NODE_XFER:
strcat(str,"at transfer menu");
break;
case NODE_RFSD:
sprintf(str+strlen(str),"retrieving from device #%d",node->aux);
break;
case NODE_DLNG:
strcat(str,"downloading");
break;
case NODE_ULNG:
strcat(str,"uploading");
break;
case NODE_BXFR:
strcat(str,"transferring bidirectional");
break;
case NODE_LFIL:
strcat(str,"listing files");
break;
case NODE_LOGN:
strcat(str,"logging on");
break;
case NODE_LCHT:
strcat(str,"in local chat with sysop");
break;
case NODE_MCHT:
if(node->aux) {
sprintf(str+strlen(str),"in multinode chat channel %d"
,node->aux&0xff);
if(node->aux&0x1f00) { /* password */
strcat(str,"* ");
unpackchatpass(str+strlen(str),node);
}
}
else
strcat(str,"in multinode global chat channel");
break;
case NODE_PAGE:
sprintf(str+strlen(str)
,"paging node %u for private chat",node->aux);
break;
case NODE_PCHT:
if(node->aux==0)
sprintf(str+strlen(str)
,"in local chat with %s"
,cfg->sys_op);
else
sprintf(str+strlen(str)
,"in private chat with node %u"
,node->aux);
break;
case NODE_GCHT:
strcat(str,"chatting with The Guru");
break;
case NODE_CHAT:
strcat(str,"in chat section");
break;
case NODE_TQWK:
strcat(str,"transferring QWK packet");
break;
case NODE_SYSP:
strcat(str,"performing sysop activities");
break;
default:
sprintf(str+strlen(str)," %s",node_connection_desc(node->connection, tmp));
if(node->action==NODE_DLNG) {
if((node->aux/60)>=12) {
if(node->aux/60==12)
hour=12;
else
hour=(node->aux/60)-12;
mer="pm";
} else {
if((node->aux/60)==0) /* 12 midnite */
hour=12;
else hour=node->aux/60;
mer="am";
}
sprintf(str+strlen(str), " ETA %02d:%02d %s"
,hour,node->aux-((node->aux/60)*60),mer);
}
}
if(node->misc&(NODE_LOCK|NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG)) {
strcat(str," (");
if(node->misc&NODE_AOFF)
strcat(str,"A");
if(node->misc&NODE_LOCK)
strcat(str,"L");

Rob Swindell
committed
if(node->misc&NODE_MSGW)
strcat(str,"M");

Rob Swindell
committed
if(node->misc&NODE_NMSG)
strcat(str,"N");
if(node->misc&NODE_POFF)
strcat(str,"P");
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
}
if(((node->misc
&(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
|| node->status==NODE_QUIET)) {
strcat(str," [");
if(node->misc&NODE_ANON)
strcat(str,"A");
if(node->misc&NODE_INTR)
strcat(str,"I");
if(node->misc&NODE_RRUN)
strcat(str,"R");
if(node->misc&NODE_UDAT)
strcat(str,"U");
if(node->status==NODE_QUIET)
strcat(str,"Q");
if(node->misc&NODE_EVENT)
strcat(str,"E");
if(node->misc&NODE_DOWN)
strcat(str,"D");
if(node->misc&NODE_LCHAT)
strcat(str,"C");
if(node->misc&NODE_FCHAT)
strcat(str,"F");
}
if(node->errors)
sprintf(str+strlen(str)
," %d error%c",node->errors, node->errors>1 ? 's' : '\0' );
strncpy(buf,str,buflen);
return(buf);
/****************************************************************************/
/* Displays the information for node number 'number' contained in 'node' */
/****************************************************************************/
void printnodedat(scfg_t* cfg, uint number, node_t* node)
{
char status[128];
printf("Node %2d: %s\n",number,nodestatus(cfg,node,status,sizeof(status),number));
/****************************************************************************/
uint finduserstr(scfg_t* cfg, uint usernumber, enum user_field fnum
,const char* str, bool del, bool next, void (*progress)(void*, int, int), void* cbdata)
int unum;
uint found = 0;
if(!VALID_CFG(cfg) || str == NULL)
if((file=openuserdat(cfg, /* for_modify: */false)) == -1)
int last = (int)filelength(file) / USER_RECORD_LINE_LEN;
unum = usernumber;
else
if(progress != NULL)
progress(cbdata, unum, last);
for(;unum <= last && found == 0; unum++) {
progress(cbdata, unum, last);
if(usernumber && unum == usernumber)
continue;
char userdat[USER_RECORD_LEN + 1];
if(readuserdat(cfg, unum, userdat, sizeof(userdat), file, /* leave_locked: */false) == 0) {
char* field[USER_FIELD_COUNT];
split_userdat(userdat, field);
if(stricmp(field[fnum], str) == 0) {
if(del || !(ahtou32(field[USER_MISC]) & (DELETED|INACTIVE)))
found = unum;
progress(cbdata, unum, last);
}
/****************************************************************************/
/* Creates a short message for 'usernumber' that contains 'strin' */
/****************************************************************************/
int putsmsg(scfg_t* cfg, int usernumber, char *strin)
{
char str[256];
int file,i;
node_t node;
if(!VALID_CFG(cfg) || !VALID_USER_NUMBER(usernumber) || strin==NULL)
if(*strin==0)
return(0);
SAFEPRINTF2(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
}
i=strlen(strin);
if(write(file,strin,i)!=i) {
close(file);
file = -1;
for(i=1;i<=cfg->sys_nodes;i++) { /* flag node if user on that msg waiting */
getnodedat(cfg,i,&node,/* lockit: */false, &file);
if(node.useron==usernumber
&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
&& !(node.misc&NODE_MSGW)) {
if(getnodedat(cfg,i,&node, /* lockit: */true, &file)==0) {
node.misc|=NODE_MSGW;
putnodedat(cfg,i,&node, /* closeit: */false, file);
}
CLOSE_OPEN_FILE(file);
/****************************************************************************/
/* Returns any short messages waiting for user number, buffer must be freed */
/****************************************************************************/
char* getsmsg(scfg_t* cfg, int usernumber)
{
int i;
int file = -1;
node_t node;
if(!VALID_CFG(cfg) || !VALID_USER_NUMBER(usernumber))
for(i=1;i<=cfg->sys_nodes;i++) { /* clear msg waiting flag */
getnodedat(cfg,i,&node, /* lockit: */false, &file);
if(node.useron==usernumber
&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
&& node.misc&NODE_MSGW) {
if(getnodedat(cfg,i,&node, /* lockit: */true, &file) == 0) {
node.misc&=~NODE_MSGW;
putnodedat(cfg,i,&node, /* closeit: */false, file);
}
CLOSE_OPEN_FILE(file);
return readsmsg(cfg, usernumber);
}
/****************************************************************************/
/* Returns any short messages waiting for user number, buffer must be freed */
/****************************************************************************/
char* readsmsg(scfg_t* cfg, int usernumber)
{
char str[MAX_PATH+1], *buf;
int file;
long length;
if(!VALID_CFG(cfg) || !VALID_USER_NUMBER(usernumber))
return(NULL);
SAFEPRINTF2(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
if(flength(str)<1L)
return(NULL);
if((file=nopen(str,O_RDWR))==-1)
return(NULL);
length=(long)filelength(file);
if(length < 0 || (buf=(char *)malloc(length+1))==NULL) {
close(file);
return(NULL);
}
if(read(file,buf,length)!=length || chsize(file, 0) != 0) {
close(file);
free(buf);
return(NULL);
}
close(file);
buf[length]=0;
strip_invalid_attr(buf);
SAFEPRINTF2(str, "%smsgs/%4.4u.last.msg", cfg->data_dir, usernumber);
backup(str, 19, /* rename: */true);
if((file = nopen(str, O_WRONLY|O_CREAT|O_APPEND)) != -1) {
int wr = write(file, buf, length);
if(wr != length) {
free(buf);
return NULL;
}
return(buf); /* caller must free */
}
char* getnmsg(scfg_t* cfg, int node_num)
{
char str[MAX_PATH+1];
char* buf;
int file = -1;
long length;
node_t node;
if(!VALID_CFG(cfg) || node_num<1)
return(NULL);
if(getnodedat(cfg,node_num,&node, /* lockit: */true, &file) == 0) {
node.misc&=~NODE_NMSG; /* clear the NMSG flag */
putnodedat(cfg,node_num,&node, /* closeit: */true, file);
}
SAFEPRINTF2(str,"%smsgs/n%3.3u.msg",cfg->data_dir,node_num);
if(flength(str)<1L)
return(NULL);
if((file=nopen(str,O_RDWR))==-1)
length=(long)filelength(file);
close(file);
}
if((buf=(char *)malloc(length+1))==NULL) {
close(file);
}
if(read(file,buf,length)!=length || chsize(file, 0) != 0) {
close(file);
free(buf);
return(NULL);
}
close(file);
buf[length]=0;
return(buf); /* caller must free */
}
/****************************************************************************/
/* Creates a short message for node 'num' that contains 'strin' */
/****************************************************************************/
int putnmsg(scfg_t* cfg, int num, char *strin)
{
char str[256];
int file,i;
node_t node;
if(!VALID_CFG(cfg) || num<1 || strin==NULL)
return(-1);
if(*strin==0)
return(0);
SAFEPRINTF2(str,"%smsgs/n%3.3u.msg",cfg->data_dir,num);
if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
(void)lseek(file,0L,SEEK_END); /* Instead of opening with O_APPEND */
i=strlen(strin);
if(write(file,strin,i)!=i) {
close(file);
}
CLOSE_OPEN_FILE(file);
getnodedat(cfg,num,&node, /* lockit: */false, &file);
if((node.status==NODE_INUSE || node.status==NODE_QUIET)
&& !(node.misc&NODE_NMSG)) {
if(getnodedat(cfg,num,&node, /* lockit: */true, &file) == 0) {
node.misc|=NODE_NMSG;
putnodedat(cfg,num,&node, /* closeit: */false, file);
}
}
CLOSE_OPEN_FILE(file);
return(0);
}
/* Return node's client's socket descriptor or negative on error */
int getnodeclient(scfg_t* cfg, uint number, client_t* client, time_t* done)
{
SOCKET sock = INVALID_SOCKET;
char path[MAX_PATH + 1];
char value[INI_MAX_VALUE_LEN];
FILE* fp;
if(!VALID_CFG(cfg)
|| client == NULL || number < 1 || number > cfg->sys_nodes)
return -1;
memset(client, 0, sizeof(*client));
client->size = sizeof(client);
SAFEPRINTF(path, "%sclient.ini", cfg->node_path[number - 1]);
fp = iniOpenFile(path, /* for_modify: */false);
if(fp == NULL)
return -2;
sock = iniReadShortInt(fp, ROOT_SECTION, "sock", 0);
client->port = iniReadShortInt(fp, ROOT_SECTION, "port", 0);
client->time = iniReadInteger(fp, ROOT_SECTION, "time", 0);
client->usernum = iniReadInteger(fp, ROOT_SECTION, "user", 0);
SAFECOPY(client->addr, iniReadString(fp, ROOT_SECTION, "addr", "<none>", value));
SAFECOPY(client->host, iniReadString(fp, ROOT_SECTION, "host", "<none>", value));
SAFECOPY(client->protocol, iniReadString(fp, ROOT_SECTION, "prot", "<unknown>", value));
SAFECOPY(client->user, iniReadString(fp, ROOT_SECTION, "name", "<unknown>", value));
*done = iniReadInteger(fp, ROOT_SECTION, "done", client->time);
fclose(fp);
return sock;
}
static bool ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user, client_t* client)
uint i,n,artype=AR_LEVEL,age;
struct tm tm;
for(;(**ptrptr);(*ptrptr)++) {
if((**ptrptr)==AR_ENDNEST)
break;
if((**ptrptr)==AR_OR) {
or=1;
if((**ptrptr)==AR_NOT) {
not=1;
if((**ptrptr)==AR_EQUAL) {
equal=1;
if((result && or) || (!result && !or))
break;
if((**ptrptr)==AR_BEGNEST) {
(*ptrptr)++;
result=!not;
else
result=not;
while((**ptrptr)!=AR_ENDNEST && (**ptrptr)) /* in case of early exit */
(*ptrptr)++;
if(!(**ptrptr))
break;
artype=(**ptrptr);
switch(artype) {
case AR_ANSI: /* No arguments */
case AR_ASCII:
case AR_UTF8:
case AR_CP437:
case AR_RIP:
case AR_WIP:
case AR_LOCAL:
case AR_EXPERT:
case AR_SYSOP:
case AR_GUEST:
case AR_QNODE:
case AR_QUIET:
case AR_OS2:
case AR_DOS:
case AR_WIN32:
case AR_UNIX:
case AR_LINUX:
case AR_ACTIVE:
case AR_INACTIVE:
case AR_DELETED:
break;
default:
(*ptrptr)++;
n=(**ptrptr);
i=(*(short *)*ptrptr);
switch(artype) {
case AR_LEVEL:
if(user==NULL
|| (equal && user->level!=n)
|| (!equal && user->level<n))