Newer
Older
/* Synchronet "@code" 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 *
* *
* 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"
#include "utf8.h"
#include "unicode.h"
#include "cp437defs.h"
#if defined(_WINSOCKAPI_)
extern WSADATA WSAData;
#define SOCKLIB_DESC WSAData.szDescription
#else
#define SOCKLIB_DESC NULL
#endif
static char* separate_thousands(const char* src, char *dest, size_t maxlen, char sep)
{
if(strlen(src) * 1.3 > maxlen)
return (char*)src;
const char* tail = src;
while(*tail && isdigit(*tail))
tail++;
if(tail == src)
return (char*)src;
size_t digits = tail - src;
char* d = dest;
for(size_t i = 0; i < digits; d++, i++) {
*d = src[i];
if(i && i + 3 < digits && (digits - (i + 1)) % 3 == 0)
*(++d) = sep;
}
*d = 0;
strcpy(d, tail);
return dest;
}
/****************************************************************************/
/* Returns 0 if invalid @ code. Returns length of @ code if valid. */
/****************************************************************************/
int sbbs_t::show_atcode(const char *instr, JSObject* obj)
char str[128],str2[128],*tp,*sp,*p;
int disp_len;

rswindell
committed
enum {
none,
left,
right,
center
} align = none;
bool zero_padded=false;
bool thousep = false; // thousands-separated
bool uppercase = false;

rswindell
committed
bool width_specified = false;
long pmode = 0;
const char *cp;
if(*instr != '@')
return 0;
tp=strchr(str+1,'@');
if(!tp) /* no terminating @ */
return(0);
if(sp && sp<tp) /* space before terminating @ */
return(0);
len=(tp-str)+1;
(*tp)=0;
sp=(str+1);
disp_len=len;
if((p = strchr(sp, '|')) != NULL) {
if(strchr(p, 'T') != NULL)
thousep = true;
if(strchr(p, 'U') != NULL)
uppercase = true;
if(strchr(p, 'L') != NULL)

rswindell
committed
align = left;
else if(strchr(p, 'R') != NULL)

rswindell
committed
align = right;
else if(strchr(p, 'C') != NULL)

rswindell
committed
align = center;
else if(strchr(p, 'W') != NULL)
doubled = true;
else if(strchr(p, 'Z') != NULL)
zero_padded = true;
else if(strchr(p, '>') != NULL)
truncated = false;
}
else if(strchr(sp, ':') != NULL)
p = NULL;
else if((p=strstr(sp,"-L"))!=NULL)

rswindell
committed
align = left;

rswindell
committed
align = right;
else if((p=strstr(sp,"-C"))!=NULL)

rswindell
committed
align = center;
else if((p=strstr(sp,"-Z"))!=NULL)
zero_padded=true;
else if((p=strstr(sp,"-T"))!=NULL)
thousep=true;
else if((p=strstr(sp,"-U"))!=NULL)
uppercase=true;
if(p!=NULL) {
char* lp = p;

rswindell
committed
lp++; // skip the '|' or '-'
while(*lp == '>'|| isalpha((uchar)*lp))
lp++;
if(*lp)
width_specified = true;
while(*lp && !isdigit((uchar)*lp))
lp++;

rswindell
committed
if(*lp && isdigit((uchar)*lp)) {

rswindell
committed
width_specified = true;
}
}

rswindell
committed
cp = atcode(sp, str2, sizeof(str2), &pmode, align == center, obj);
if(cp==NULL)
char separated[128];
if(thousep)
cp = separate_thousands(cp, separated, sizeof(separated), ',');
if(uppercase) {
char upper[128];
SAFECOPY(upper, cp);
strupr(upper);
cp = upper;
}

rswindell
committed
if(p==NULL || truncated == false || (width_specified == false && align == none))

rswindell
committed
if(uppercase && align == none)
align = left;
if(truncated) {
if(column + disp_len > cols - 1) {
if(column >= cols - 1)
disp_len = 0;
else
disp_len = (cols - 1) - column;
}
}
if(pmode & P_UTF8) {
if(term_supports(UTF8))
disp_len += strlen(cp) - utf8_str_total_width(cp);
else
disp_len += strlen(cp) - utf8_str_count_width(cp, /* min: */1, /* max: */2);
}

rswindell
committed
if(align == left)
bprintf(pmode, "%-*.*s",disp_len,disp_len,cp);

rswindell
committed
else if(align == right)
bprintf(pmode, "%*.*s",disp_len,disp_len,cp);

rswindell
committed
else if(align == center) {
if(vlen < disp_len) {
int left = (disp_len - vlen) / 2;
bprintf(pmode, "%*s%-*s", left, "", disp_len - left, cp);
bprintf(pmode, "%.*s", disp_len, cp);
} else if(zero_padded) {
int vlen = strlen(cp);
if(vlen < disp_len)
bprintf(pmode, "%-.*s%s", (int)(disp_len - strlen(cp)), "0000000000", cp);
else
bprintf(pmode, "%.*s", disp_len, cp);
bprintf(pmode, "%.*s", disp_len, cp);
static const char* getpath(scfg_t* cfg, const char* path)
{
for(int i = 0; i < cfg->total_dirs; i++) {
if(stricmp(cfg->dir[i]->code, path) == 0)
return cfg->dir[i]->path;
}
return path;
}
const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool centered, JSObject* obj)
char* tp = NULL;
uint ugrp;
uint usub;
long l;
stats_t stats;
node_t node;
struct tm tm;
str[0]=0;
if(strncmp(sp, "U+", 2) == 0) { // UNICODE
enum unicode_codepoint codepoint = (enum unicode_codepoint)strtoul(sp + 2, &tp, 16);
outchar(codepoint, unicode_to_cp437(codepoint));
else if(*tp == ':')
outchar(codepoint, tp + 1);
else {
char fallback = (char)strtoul(tp + 1, NULL, 16);
outchar(codepoint, fallback);
else if(*tp == '!') {
char ch = unicode_to_cp437(codepoint);
if(ch != 0)
fallback = ch;
outchar(codepoint, fallback);
}
else return NULL; // Invalid @-code
}
return nulstr;
}
if(strcmp(sp, "CHECKMARK") == 0) {
outchar(UNICODE_CHECK_MARK, CP437_CHECK_MARK);
return nulstr;
}
if(strcmp(sp, "ELLIPSIS") == 0) {
outchar(UNICODE_HORIZONTAL_ELLIPSIS, "...");
return nulstr;
}
if(strcmp(sp, "COPY") == 0) {
outchar(UNICODE_COPYRIGHT_SIGN, "(C)");
return nulstr;
}
if(strcmp(sp, "SOUNDCOPY") == 0) {
outchar(UNICODE_SOUND_RECORDING_COPYRIGHT, "(P)");
return nulstr;
}
if(strcmp(sp, "REGISTERED") == 0) {
outchar(UNICODE_REGISTERED_SIGN, "(R)");
return nulstr;
}
if(strcmp(sp, "TRADEMARK") == 0) {
outchar(UNICODE_TRADE_MARK_SIGN, "(TM)");
return nulstr;
}
if(strcmp(sp, "DEGREE_C") == 0) {
return nulstr;
}
if(strcmp(sp, "DEGREE_F") == 0) {
if(strncmp(sp, "WIDE:", 5) == 0) {
wide(sp + 5);
return(nulstr);
}
safe_snprintf(str,maxlen,"%c",REVISION);
safe_snprintf(str,maxlen,"%s%c%s",VERSION,REVISION,beta_version);

rswindell
committed
#if defined(_DEBUG)

rswindell
committed
#endif

rswindell
committed
}
if(!strcmp(sp,"VER_NOTICE"))

rswindell
committed
if(!strcmp(sp,"OS_VER"))
return(os_version(str));

rswindell
committed
#ifdef JAVASCRIPT
if(!strcmp(sp,"JS_VER"))
return((char *)JS_GetImplementationVersion());

rswindell
committed
#endif
if(!strcmp(sp,"PLATFORM"))
return(PLATFORM_DESC);

rswindell
committed
if(!strcmp(sp,"COPYRIGHT"))
return(COPYRIGHT_NOTICE);

rswindell
committed
char compiler[32];
DESCRIBE_COMPILER(compiler);
strncpy(str, compiler, maxlen);

rswindell
committed
}
extern volatile time_t uptime;
time_t up=0;
now = time(NULL);
if (uptime != 0 && now >= uptime)
up = now-uptime;
char days[64]="";
if((up/(24*60*60))>=2) {
sprintf(days,"%lu days ",(ulong)(up/(24L*60L*60L)));
up%=(24*60*60);
}
safe_snprintf(str,maxlen,"%s%lu:%02lu"
,(ulong)(up/(60L*60L))
,(ulong)((up/60L)%60L)
if(!strcmp(sp,"SERVED")) {
extern volatile ulong served;
safe_snprintf(str,maxlen,"%lu",served);
return(str);
}
if(!strcmp(sp,"SOCKET_LIB"))
return(socklib_version(str,SOCKLIB_DESC));

rswindell
committed
safe_snprintf(str,maxlen,"SMBLIB %s",smb_lib_ver());

rswindell
committed
if(!strcmp(sp,"BBS") || !strcmp(sp,"BOARDNAME"))
return(cfg.sys_name);
if(!strcmp(sp,"BAUD") || !strcmp(sp,"BPS")) {
safe_snprintf(str,maxlen,"%lu",cur_output_rate ? cur_output_rate : cur_rate);
if(!strcmp(sp,"COLS")) {
safe_snprintf(str,maxlen,"%lu",cols);
return(str);
}
if(!strcmp(sp,"ROWS")) {
safe_snprintf(str,maxlen,"%lu",rows);
return(str);
}
if(strcmp(sp,"TERM") == 0)
return term_type();
if(strcmp(sp,"CHARSET") == 0)
return term_charset();
if(!strcmp(sp,"CONN"))
return(connection);
if(!strcmp(sp,"SYSOP"))
return(cfg.sys_op);
if(!strcmp(sp,"LOCATION"))
return(cfg.sys_location);
if(strcmp(sp,"NODE") == 0 || strcmp(sp,"NN") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.node_num);
if(strcmp(sp, "TNODES") == 0 || strcmp(sp, "TNODE") == 0 || strcmp(sp, "TN") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.sys_nodes);
if(strcmp(sp, "ANODES") == 0 || strcmp(sp, "ANODE") == 0 || strcmp(sp, "AN") == 0) {
safe_snprintf(str, maxlen, "%u", count_nodes(/* self: */true));
return str;
}
if(strcmp(sp, "ONODES") == 0 || strcmp(sp, "ONODE") == 0 || strcmp(sp, "ON") == 0) {
safe_snprintf(str, maxlen, "%u", count_nodes(/* self: */false));
return str;
}
if(strcmp(sp, "PWDAYS") == 0) {
if(cfg.sys_pwdays) {
safe_snprintf(str, maxlen, "%u", cfg.sys_pwdays);
return str;
}
return text[Unlimited];
}
if(strcmp(sp, "AUTODEL") == 0) {
if(cfg.sys_autodel) {
safe_snprintf(str, maxlen, "%u", cfg.sys_autodel);
return str;
}
return text[Unlimited];
}
if(strcmp(sp, "PAGER") == 0)
return (thisnode.misc&NODE_POFF) ? text[Off] : text[On];
if(strcmp(sp, "ALERTS") == 0)
return (thisnode.misc&NODE_AOFF) ? text[Off] : text[On];
if(strcmp(sp, "SPLITP") == 0)
return (useron.chat&CHAT_SPLITP) ? text[On] : text[Off];
if(!strcmp(sp,"INETADDR"))
return(cfg.sys_inetaddr);
if(!strcmp(sp,"HOSTNAME"))
return(startup->host_name);
return(smb_faddrtoa(&cfg.faddr[0],str));
if(!strcmp(sp,"EMAILADDR"))
,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name));
if(!strcmp(sp,"QWKID"))
return(cfg.sys_id);
if(!strcmp(sp,"TIME") || !strcmp(sp,"SYSTIME")) {
memset(&tm,0,sizeof(tm));
if(cfg.sys_misc&SM_MILITARY)
safe_snprintf(str,maxlen,"%02d:%02d:%02d"
,tm.tm_hour,tm.tm_min,tm.tm_sec);
else
safe_snprintf(str,maxlen,"%02d:%02d %s"
,tm.tm_hour==0 ? 12
: tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
if(!strcmp(sp,"TIMEZONE"))
return(smb_zonestr(sys_timezone(&cfg),str));
if(!strcmp(sp,"DATE") || !strcmp(sp,"SYSDATE")) {
return(unixtodstr(&cfg,time32(NULL),str));
if(!strcmp(sp,"DATETIME"))
return(timestr(time(NULL)));
if(!strcmp(sp,"DATETIMEZONE")) {
char zone[32];
safe_snprintf(str, maxlen, "%s %s", timestr(time(NULL)), smb_zonestr(sys_timezone(&cfg),zone));
return str;
}
if(strcmp(sp, "DATEFMT") == 0) {
return cfg.sys_misc&SM_EURODATE ? "DD/MM/YY" : "MM/DD/YY";
}
l=0;
for(i=0;i<cfg.total_subs;i++)
l+=getposts(&cfg,i); /* l=total posts */
safe_snprintf(str,maxlen,"%lu",l);
safe_snprintf(str,maxlen,"%u",total_users(&cfg));
l=0;
for(i=0;i<cfg.total_dirs;i++)
safe_snprintf(str,maxlen,"%lu",l);
if(strncmp(sp, "FILES:", 6) == 0) { // Number of files in specified directory
const char* path = getpath(&cfg, sp + 6);
safe_snprintf(str, maxlen, "%lu", getfilecount(path));
}
if(strcmp(sp, "FILES") == 0) { // Number of files in current directory
safe_snprintf(str, maxlen, "%lu", (ulong)getfiles(&cfg, usrdir[curlib][curdir[curlib]]));
return str;
}
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
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
586
587
588
589
590
591
592
593
594
if(strncmp(sp, "FILESIZE:", 9) == 0) {
const char* path = getpath(&cfg, sp + 9);
byte_estimate_to_str(getfilesizetotal(path), str, maxlen, /* unit: */1, /* precision: */1);
return str;
}
if(strcmp(sp, "FILESIZE") == 0) {
byte_estimate_to_str(getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path)
,str, maxlen, /* unit: */1, /* precision: */1);
return str;
}
if(strncmp(sp, "FILEBYTES:", 10) == 0) { // Number of bytes in current file directory
const char* path = getpath(&cfg, sp + 10);
safe_snprintf(str, maxlen, "%" PRIu64, getfilesizetotal(path));
return str;
}
if(strcmp(sp, "FILEBYTES") == 0) { // Number of bytes in current file directory
safe_snprintf(str, maxlen, "%" PRIu64
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path));
return str;
}
if(strncmp(sp, "FILEKB:", 7) == 0) { // Number of kibibytes in current file directory
const char* path = getpath(&cfg, sp + 7);
safe_snprintf(str, maxlen, "%1.1f", getfilesizetotal(path) / 1024.0);
return str;
}
if(strcmp(sp, "FILEKB") == 0) { // Number of kibibytes in current file directory
safe_snprintf(str, maxlen, "%1.1f"
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path) / 1024.0);
return str;
}
if(strncmp(sp, "FILEMB:", 7) == 0) { // Number of mebibytes in current file directory
const char* path = getpath(&cfg, sp + 7);
safe_snprintf(str, maxlen, "%1.1f", getfilesizetotal(path) / (1024.0 * 1024.0));
return str;
}
if(strcmp(sp, "FILEMB") == 0) { // Number of mebibytes in current file directory
safe_snprintf(str, maxlen, "%1.1f"
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path) / (1024.0 * 1024.0));
return str;
}
if(strncmp(sp, "FILEGB:", 7) == 0) { // Number of gibibytes in current file directory
const char* path = getpath(&cfg, sp + 7);
safe_snprintf(str, maxlen, "%1.1f", getfilesizetotal(path) / (1024.0 * 1024.0 * 1024.0));
return str;
}
if(strcmp(sp, "FILEGB") == 0) { // Number of gibibytes in current file directory
safe_snprintf(str, maxlen, "%1.1f"
,getfilesizetotal(cfg.dir[usrdir[curlib][curdir[curlib]]]->path) / (1024.0 * 1024.0 * 1024.0));
return str;
}
if(!strcmp(sp,"TCALLS") || !strcmp(sp,"NUMCALLS")) {
safe_snprintf(str,maxlen,"%lu", (ulong)stats.logons);
if(!strcmp(sp,"PREVON") || !strcmp(sp,"LASTCALLERNODE")
|| !strcmp(sp,"LASTCALLERSYSTEM"))
if(!strcmp(sp,"PAUSE") || !strcmp(sp,"MORE")) {
lncntr=0;
if(!strcmp(sp,"NOPAUSE") || !strcmp(sp,"POFF")) {
if(!strcmp(sp,"PON") || !strcmp(sp,"AUTOMORE")) {
long margin = centered ? column : 1;
if(margin < 1) margin = 1;
while(*sp && online && column < cols - margin)
bputs(sp, P_TRUNCATE);
return nulstr;
}
if(strncmp(sp, "POS:", 4) == 0) { // PCBoard (nn is 1 based)
i = atoi(sp + 4);
if(i >= 1) // Convert to 0-based
i--;
for(l = i - column; l > 0; l--)
outchar(' ');
return nulstr;
}
if(strncmp(sp, "DELAY:", 6) == 0) { // PCBoard
mswait(atoi(sp + 6) * 100);
return nulstr;
}
if(strcmp(sp, "YESCHAR") == 0) { // PCBoard
safe_snprintf(str, maxlen, "%c", text[YNQP][0]);
return str;
}
if(strcmp(sp, "NOCHAR") == 0) { // PCBoard
safe_snprintf(str, maxlen, "%c", text[YNQP][1]);
return str;
}
if(strcmp(sp, "QUITCHAR") == 0) {
safe_snprintf(str, maxlen, "%c", text[YNQP][2]);
return str;
}
if(strncmp(sp, "BPS:", 4) == 0) {
set_output_rate((enum output_rate)atoi(sp + 4));
return nulstr;
}
/* NOSTOP */
/* STOP */
if(!strcmp(sp,"BELL") || !strcmp(sp,"BEEP"))
return("\a");
if(!strcmp(sp,"EVENT")) {
if(event_time==0)
return("<none>");
return(timestr(event_time));
i=atoi(sp+4);
if(i && i<=cfg.sys_nodes) {
getnodedat(i,&node,0);
printnodedat(i,&node);
}
if(!strcmp(sp,"USER") || !strcmp(sp,"ALIAS") || !strcmp(sp,"NAME"))
return(useron.alias);
safe_snprintf(str,maxlen,"%s",useron.alias);
return(str);
safe_snprintf(str,maxlen,"%u",useron.number);
if(!strcmp(sp,"PHONE") || !strcmp(sp,"HOMEPHONE")
|| !strcmp(sp,"DATAPHONE") || !strcmp(sp,"DATA"))
if(!strcmp(sp,"ADDR1"))
return(useron.address);
if(!strcmp(sp,"FROM"))
return(useron.location);
safe_snprintf(str,maxlen,"%s",useron.location);
return(str);
}
if(!strcmp(sp,"STATE")) {
char* p=strchr(useron.location,',');
return(p);
}
if(!strcmp(sp,"CPU"))
return(useron.comp);
if(!strcmp(sp,"HOST"))
return(client_name);
if(!strcmp(sp,"BDATE"))
return(useron.birth);
safe_snprintf(str,maxlen,"%u",getage(&cfg,useron.birth));
if(!strcmp(sp,"CALLS") || !strcmp(sp,"NUMTIMESON")) {
safe_snprintf(str,maxlen,"%u",useron.logons);
if(strcmp(sp, "PWAGE") == 0) {
time_t age = time(NULL) - useron.pwmod;
safe_snprintf(str, maxlen, "%ld", (long)(age/(24*60*60)));
return str;
}
if(strcmp(sp, "PWDATE") == 0 || strcmp(sp, "MEMO") == 0)
return(unixtodstr(&cfg,useron.pwmod,str));
if(!strcmp(sp,"SEC") || !strcmp(sp,"SECURITY")) {
safe_snprintf(str,maxlen,"%u",useron.level);
if(!strcmp(sp,"SINCE"))
return(unixtodstr(&cfg,useron.firston,str));
if(!strcmp(sp,"TIMEON") || !strcmp(sp,"TIMEUSED")) {
safe_snprintf(str,maxlen,"%lu",(ulong)(now-logontime)/60L);
if(!strcmp(sp,"TUSED")) { /* Synchronet only */
return(sectostr((uint)(now-logontime),str)+1);
if(!strcmp(sp,"TLEFT")) { /* Synchronet only */
return(sectostr(timeleft,str)+1);
if(!strcmp(sp,"TPERD")) /* Synchronet only */
if(!strcmp(sp,"TPERC")) /* Synchronet only */
safe_snprintf(str,maxlen,"%u",cfg.level_timepercall[useron.level]);
if(strcmp(sp, "MPERD") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_timeperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXCALLS") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_callsperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXPOSTS") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_postsperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXMAILS") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_emailperday[useron.level]);
return str;
}
if(strcmp(sp, "MAXLINES") == 0) {
safe_snprintf(str,maxlen,"%u",cfg.level_linespermsg[useron.level]);
return str;
}
if(!strcmp(sp,"MINLEFT") || !strcmp(sp,"LEFT") || !strcmp(sp,"TIMELEFT")) {
safe_snprintf(str,maxlen,"%lu",timeleft/60);
if(!strcmp(sp,"LASTON"))
return(timestr(useron.laston));
if(!strcmp(sp,"LASTDATEON"))
return(unixtodstr(&cfg,useron.laston,str));
memset(&tm,0,sizeof(tm));
localtime32(&useron.laston,&tm);
if(cfg.sys_misc&SM_MILITARY)
safe_snprintf(str,maxlen,"%02d:%02d:%02d"
,tm.tm_hour, tm.tm_min, tm.tm_sec);
else
safe_snprintf(str,maxlen,"%02d:%02d %s"
,tm.tm_hour==0 ? 12
: tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
if(!strcmp(sp,"FIRSTON"))
return(timestr(useron.firston));
if(!strcmp(sp,"FIRSTDATEON"))
return(unixtodstr(&cfg,useron.firston,str));
if(!strcmp(sp,"FIRSTTIMEON")) {
memset(&tm,0,sizeof(tm));
localtime32(&useron.firston,&tm);
if(cfg.sys_misc&SM_MILITARY)
safe_snprintf(str,maxlen,"%02d:%02d:%02d"
,tm.tm_hour, tm.tm_min, tm.tm_sec);
else
safe_snprintf(str,maxlen,"%02d:%02d %s"
,tm.tm_hour==0 ? 12
: tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
return(str);
}
if(strcmp(sp, "EMAILS") == 0) {
safe_snprintf(str, maxlen, "%u", useron.emails);
return str;
}
if(strcmp(sp, "FBACKS") == 0) {
safe_snprintf(str, maxlen, "%u", useron.fbacks);
return str;
}
if(strcmp(sp, "ETODAY") == 0) {
safe_snprintf(str, maxlen, "%u", useron.etoday);
return str;
}
if(strcmp(sp, "PTODAY") == 0) {
safe_snprintf(str, maxlen, "%u", useron.ptoday);
return str;
}
if(strcmp(sp, "LTODAY") == 0) {
safe_snprintf(str, maxlen, "%u", useron.ltoday);
return str;
}
safe_snprintf(str, maxlen, "%u", useron.ttoday);
return str;
}
if(strcmp(sp, "MTOTAL") == 0) {
safe_snprintf(str, maxlen, "%u", useron.timeon);
return str;
}
if(strcmp(sp, "TTODAY") == 0)
if(strcmp(sp, "TLAST") == 0) {
safe_snprintf(str, maxlen, "%u", useron.tlast);
return str;
}
safe_snprintf(str, maxlen, "%u", useron.textra);
return str;
}
if(strcmp(sp, "TEXTRA") == 0)
return sectostr(useron.textra, str) + 3;
if(strcmp(sp, "MBANKED") == 0) {
safe_snprintf(str, maxlen, "%lu", useron.min);
return str;
}
if(strcmp(sp, "TBANKED") == 0)
return sectostr(useron.min, str) + 3;
if(!strcmp(sp,"MSGLEFT") || !strcmp(sp,"MSGSLEFT")) {
safe_snprintf(str,maxlen,"%u",useron.posts);
safe_snprintf(str,maxlen,"%lu",posts_read);
safe_snprintf(str,maxlen,"%lu",getfreediskspace(cfg.temp_dir,0));
return(str);
}
if(!strcmp(sp,"FREESPACEK")) {
safe_snprintf(str,maxlen,"%lu",getfreediskspace(cfg.temp_dir,1024));
safe_snprintf(str,maxlen,"%lu",useron.ulb);
safe_snprintf(str,maxlen,"%lu",useron.ulb/1024L);
if(!strcmp(sp,"UPS") || !strcmp(sp,"UPFILES")) {
safe_snprintf(str,maxlen,"%u",useron.uls);
safe_snprintf(str,maxlen,"%lu",useron.dlb);
safe_snprintf(str,maxlen,"%lu",useron.dlb/1024L);
if(!strcmp(sp,"DOWNS") || !strcmp(sp,"DLFILES")) {
safe_snprintf(str,maxlen,"%u",useron.dls);