Newer
Older
/* Synchronet "@code" functions */
/****************************************************************************
* @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 *
* *
* 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"
#include "utf8.h"
#include "unicode.h"
#include "cp437defs.h"
#include "ver.h"
#include "petdefs.h"
#include "filedat.h"
#if defined(_WINSOCKAPI_)
extern WSADATA WSAData;
#define SOCKLIB_DESC WSAData.szDescription
#else
#define SOCKLIB_DESC NULL
#endif
struct atcode_format {
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;
char* parse(char* sp) {
char* p;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
disp_len=strlen(sp) + 2;
if((p = strchr(sp, '|')) != NULL) {
if(strchr(p, 'T') != NULL)
thousep = true;
if(strchr(p, 'U') != NULL)
uppercase = true;
if(strchr(p, 'L') != NULL)
align = left;
else if(strchr(p, 'R') != NULL)
align = right;
else if(strchr(p, 'C') != NULL)
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)
align = left;
else if((p=strstr(sp,"-R"))!=NULL)
align = right;
else if((p=strstr(sp,"-C"))!=NULL)
align = center;
else if((p=strstr(sp,"-W"))!=NULL) /* wide */
doubled=true;
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;
else if((p=strstr(sp,"->"))!=NULL) /* wrap */
truncated = false;
if(p!=NULL) {
char* lp = p;
lp++; // skip the '|' or '-'
while(*lp == '>'|| IS_ALPHA(*lp))
lp++;
if(*lp)
width_specified = true;
while(*lp && !IS_DIGIT(*lp))
lp++;
if(*lp && IS_DIGIT(*lp)) {
disp_len=atoi(lp);
width_specified = true;
}
*p=0;
}
return p;
}
};
/****************************************************************************/
/* 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 len;
atcode_format fmt;
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);

rswindell
committed
if(*sp == '~' && *(sp + 1)) { // Mouse hot-spot (hungry)
sp++;
tp = strchr(sp + 1, '~');
if(tp == NULL)
tp = sp;
else {
*tp = 0;
tp++;
}
c_unescape_str(tp);

rswindell
committed
add_hotspot(tp, /* hungry: */true, column, column + strlen(sp) - 1, row);
bputs(sp);
return len;
}
if(*sp == '`' && *(sp + 1)) { // Mouse hot-spot (strict)
sp++;
tp = strchr(sp + 1, '`');
if(tp == NULL)
tp = sp;
else {
*tp = 0;
tp++;
}
c_unescape_str(tp);
add_hotspot(tp, /* hungry: */false, column, column + strlen(sp) - 1, row);
// @!x@ for Ctrl-A x equivalent(s) */
if(*sp == '!') {
for(p = sp + 1; *p != '\0' && *p != '@'; p++)
ctrl_a(*p);
return len;
}
p = fmt.parse(sp);
cp = atcode(sp, str2, sizeof(str2), &pmode, fmt.align == fmt.center, obj);
if(cp==NULL)
char separated[128];
if(fmt.thousep)
cp = separate_thousands(cp, separated, sizeof(separated), ',');
if(fmt.uppercase) {
SAFECOPY(upper, cp);
strupr(upper);
cp = upper;
}
if(p==NULL || fmt.truncated == false || (fmt.width_specified == false && fmt.align == fmt.none))
fmt.disp_len = strlen(cp);
if(fmt.uppercase && fmt.align == fmt.none)
fmt.align = fmt.left;

rswindell
committed
if(fmt.truncated && strchr(cp, '\n') == NULL) {
if(column + fmt.disp_len > cols - 1) {
fmt.disp_len = 0;
fmt.disp_len = (cols - 1) - column;
if(pmode & P_UTF8) {
if(term_supports(UTF8))
fmt.disp_len += strlen(cp) - utf8_str_total_width(cp, unicode_zerowidth);
else
fmt.disp_len += strlen(cp) - utf8_str_count_width(cp, /* min: */1, /* max: */2, unicode_zerowidth);
}
if(fmt.align == fmt.left)
bprintf(pmode, "%-*.*s",fmt.disp_len,fmt.disp_len,cp);
else if(fmt.align == fmt.right)
bprintf(pmode, "%*.*s",fmt.disp_len,fmt.disp_len,cp);
else if(fmt.align == fmt.center) {
if(vlen < fmt.disp_len) {
int left = (fmt.disp_len - vlen) / 2;
bprintf(pmode, "%*s%-*s", left, "", fmt.disp_len - left, cp);
bprintf(pmode, "%.*s", fmt.disp_len, cp);
} else if(fmt.doubled) {
} else if(fmt.zero_padded) {
int vlen = strlen(cp);
if(vlen < fmt.disp_len)
bprintf(pmode, "%-.*s%s", (int)(fmt.disp_len - strlen(cp)), "0000000000", cp);
else
bprintf(pmode, "%.*s", fmt.disp_len, cp);
bprintf(pmode, "%.*s", fmt.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::formatted_atcode(const char* sp, char* str, size_t maxlen)
{
char tmp[128];
char buf[256];
atcode_format fmt;
SAFECOPY(tmp, sp);
char* p = fmt.parse(tmp);
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
const char* cp = atcode(tmp, buf, sizeof buf);
if(cp == nullptr)
return nullptr;
char separated[128];
if(fmt.thousep)
cp = separate_thousands(cp, separated, sizeof(separated), ',');
char upper[128];
if(fmt.uppercase) {
SAFECOPY(upper, cp);
strupr(upper);
cp = upper;
}
if(p==NULL || fmt.truncated == false || (fmt.width_specified == false && fmt.align == fmt.none))
fmt.disp_len = strlen(cp);
if(fmt.align == fmt.left)
snprintf(str, maxlen, "%-*.*s", fmt.disp_len, fmt.disp_len, cp);
else if(fmt.align == fmt.right)
snprintf(str, maxlen, "%*.*s", fmt.disp_len, fmt.disp_len, cp);
else if(fmt.align == fmt.center) {
int vlen = strlen(cp);
if(vlen < fmt.disp_len) {
int left = (fmt.disp_len - vlen) / 2;
snprintf(str, maxlen, "%*s%-*s", left, "", fmt.disp_len - left, cp);
} else
snprintf(str, maxlen, "%.*s", fmt.disp_len, cp);
// } else if(fmt.doubled) { // Unsupported in this context
// wide(cp);
} else if(fmt.zero_padded) {
int vlen = strlen(cp);
if(vlen < fmt.disp_len)
snprintf(str, maxlen, "%-.*s%s", (int)(fmt.disp_len - strlen(cp)), "0000000000", cp);
else
snprintf(str, maxlen, "%.*s", fmt.disp_len, cp);
} else
snprintf(str, maxlen, "%.*s", fmt.disp_len, cp);
return str;
}

Rob Swindell
committed
const char* sbbs_t::atcode(const char* sp, char* str, size_t maxlen, int* pmode, bool centered, JSObject* obj)

Rob Swindell
committed
char tmp[128];
char* tp = NULL;

Rob Swindell
committed
int i;
uint ugrp;
uint usub;
long l;
stats_t stats;
node_t node;
struct tm tm;
str[0]=0;
if(strcmp(sp, "SHOW") == 0) {
console &= ~CON_ECHO_OFF;
return nulstr;
}
if(strncmp(sp, "SHOW:", 5) == 0) {
uchar* ar = arstr(NULL, sp + 5, &cfg, NULL);
if(ar != NULL) {
if(!chk_ar(ar, &useron, &client))
console |= CON_ECHO_OFF;
else
console &= ~CON_ECHO_OFF;
free(ar);
}
return nulstr;
}
if(strcmp(sp, "HOT") == 0) { // Auto-mouse hot-spot attribute
hot_attr = curatr;
return nulstr;

rswindell
committed
if(strncmp(sp, "HOT:", 4) == 0) { // Auto-mouse hot-spot attribute

rswindell
committed
if(stricmp(sp, "hungry") == 0) {
hungry_hotspots = true;
hot_attr = curatr;
}
else if(stricmp(sp, "strict") == 0) {
hungry_hotspots = false;
hot_attr = curatr;
}
else if(stricmp(sp, "off") == 0)
hot_attr = strtoattr(sp, /* endptr: */NULL);

rswindell
committed
return nulstr;
}
if(strcmp(sp, "CLEAR_HOT") == 0) {
clear_hotspots();
return nulstr;
}

rswindell
committed
if(strncmp(sp, "MNE:", 4) == 0) { // Mnemonic attribute control
sp += 4;
mneattr_low = strtoattr(sp, &tp);
mneattr_high = mneattr_low ^ HIGH;
if(tp != NULL && *tp != '\0')
mneattr_high = strtoattr(tp + 1, &tp);
if(tp != NULL && *tp != '\0')
mneattr_cmd = strtoattr(tp + 1, NULL);
return nulstr;
}
if(strncmp(sp, "RAINBOW:", 8) == 0) {
memset(rainbow, 0, sizeof rainbow);
parse_attr_str_list(rainbow, LEN_RAINBOW, sp + 8);
return nulstr;
}
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
return(os_version(str, maxlen));
if(strcmp(sp,"OS_CPU") == 0)
return(os_cpuarch(str, maxlen));

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
}
if(strcmp(sp, "GIT_HASH") == 0)
return git_hash;
if(strcmp(sp, "GIT_BRANCH") == 0)
return git_branch;
if(strcmp(sp, "GIT_DATE") == 0)
return git_date;
if(strcmp(sp, "BUILD_DATE") == 0)
return __DATE__;
if(strcmp(sp, "BUILD_TIME") == 0)
return __TIME__;
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) {
snprintf(days, sizeof days, "%u days ",(uint)(up/(24L*60L*60L)));
up%=(24*60*60);
}
safe_snprintf(str,maxlen,"%s%u:%02u"
,(uint)(up/(60L*60L))
,(uint)((up/60L)%60L)
if(!strcmp(sp,"SERVED")) {
extern volatile uint served;
safe_snprintf(str,maxlen,"%u",served);
return(str);
}
if(!strcmp(sp,"SOCKET_LIB"))
return(socklib_version(str, maxlen, 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,"%u",cur_output_rate ? cur_output_rate : cur_rate);
if(!strcmp(sp,"CPS")) {
safe_snprintf(str,maxlen,"%u",cur_cps);
return(str);
}
safe_snprintf(str,maxlen,"%u",cols);
safe_snprintf(str,maxlen,"%u",rows);
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, "SYSAVAIL") == 0)
return text[sysop_available(&cfg) ? LiSysopAvailable : LiSysopNotAvailable];
if(strcmp(sp, "SYSAVAILYN") == 0)
return text[sysop_available(&cfg) ? Yes : No];
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 server_host_name();
return(smb_faddrtoa(&cfg.faddr[0],str));
if(!strcmp(sp,"EMAILADDR"))
,(cfg.inetmail_misc&NMAIL_ALIAS) || (useron.rest&FLAG('O')) ? useron.alias : useron.name));
if(strcmp(sp, "NETMAIL") == 0)
return useron.netmail;

Rob Swindell
committed
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
if(strcmp(sp, "TERMTYPE") == 0)
return term_type(&useron, term_supports(), str, maxlen);
if(strcmp(sp, "TERMROWS") == 0)
return term_rows(&useron, str, maxlen);
if(strcmp(sp, "TERMCOLS") == 0)
return term_cols(&useron, str, maxlen);
if(strcmp(sp, "AUTOTERM") == 0)
return (useron.misc & AUTOTERM) ? text[On] : text[Off];
if(strcmp(sp, "ANSI") == 0)
return (useron.misc & ANSI) ? text[On] : text[Off];
if(strcmp(sp, "ASCII") == 0)
return (useron.misc & NO_EXASCII) ? text[On] : text[Off];
if(strcmp(sp, "COLOR") == 0)
return (useron.misc & COLOR) ? text[On] : text[Off];
if(strcmp(sp, "ICE") == 0)
return (useron.misc & ICE_COLOR) ? text[On] : text[Off];
if(strcmp(sp, "RIP") == 0)
return (useron.misc & RIP) ? text[On] : text[Off];
if(strcmp(sp, "PETSCII") == 0)
return (useron.misc & PETSCII) ? text[On] : text[Off];
if(strcmp(sp, "PETGRFX") == 0) {
if(term_supports(PETSCII))
outcom(PETSCII_UPPERGRFX);
return nulstr;
}

Rob Swindell
committed
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
if(strcmp(sp, "SWAPDEL") == 0)
return (useron.misc & SWAP_DELETE) ? text[On] : text[Off];
if(strcmp(sp, "UTF8") == 0)
return (useron.misc & UTF8) ? text[On] : text[Off];
if(strcmp(sp, "MOUSE") == 0)
return (useron.misc & MOUSE) ? text[On] : text[Off];
if(strcmp(sp, "UPAUSE") == 0)
return (useron.misc & UPAUSE) ? text[On] : text[Off];
if(strcmp(sp, "SPIN") == 0)
return (useron.misc & SPIN) ? text[On] : text[Off];
if(strcmp(sp, "PAUSESPIN") == 0)
return (useron.misc & NOPAUSESPIN) ? text[Off] : text[On];
if(strcmp(sp, "EXPERT") == 0)
return (useron.misc & EXPERT) ? text[On] : text[Off];
if(strcmp(sp, "HOTKEYS") == 0)
return (useron.misc & COLDKEYS) ? text[Off] : text[On];
if(strcmp(sp, "MSGCLS") == 0)
return (useron.misc & CLRSCRN) ? text[On] : text[Off];
if(strcmp(sp, "FWD") == 0)
return (useron.misc & NETMAIL) ? text[On] : text[Off];

Rob Swindell
committed
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
if(strcmp(sp, "REMSUBS") == 0)
return (useron.misc & CURSUB) ? text[On] : text[Off];
if(strcmp(sp, "FILEDESC") == 0)
return (useron.misc & EXTDESC) ? text[On] : text[Off];
if(strcmp(sp, "FILEFLAG") == 0)
return (useron.misc & BATCHFLAG) ? text[On] : text[Off];
if(strcmp(sp, "AUTOHANG") == 0)
return (useron.misc & AUTOHANG) ? text[On] : text[Off];
if(strcmp(sp, "AUTOLOGON") == 0)
return (useron.misc & AUTOLOGON) ? text[On] : text[Off];
if(strcmp(sp, "QUIET") == 0)
return (useron.misc & QUIET) ? text[On] : text[Off];
if(strcmp(sp, "ASKNSCAN") == 0)
return (useron.misc & ASK_NSCAN) ? text[On] : text[Off];
if(strcmp(sp, "ASKSSCAN") == 0)
return (useron.misc & ASK_SSCAN) ? text[On] : text[Off];
if(strcmp(sp, "ANFSCAN") == 0)
return (useron.misc & ANFSCAN) ? text[On] : text[Off];
if(strcmp(sp, "EDITOR") == 0)
return (useron.xedit < 1 || useron.xedit >= cfg.total_xedits) ? text[None] : cfg.xedit[useron.xedit - 1]->name;
if(strcmp(sp, "SHELL") == 0)
return cfg.shell[useron.shell]->name;
if(strcmp(sp, "TMP") == 0)
return useron.tmpext;
if(strcmp(sp, "PROT") == 0) {
safe_snprintf(str, maxlen, "%c", useron.prot);
return str;
}

Rob Swindell
committed
if(strcmp(sp, "PROTNAME") == 0)
return protname(useron.prot);
if(strcmp(sp, "SEX") == 0) {
safe_snprintf(str, maxlen, "%c", useron.sex);
return str;
}
if(strcmp(sp, "GENDERS") == 0) {
return cfg.new_genders;
}
if(!strcmp(sp,"QWKID"))
return(cfg.sys_id);
if(!strcmp(sp,"TIME") || !strcmp(sp,"SYSTIME") || !strcmp(sp,"TIME_UTC")) {
memset(&tm,0,sizeof(tm));
if(strcmp(sp, "TIME_UTC") == 0)
gmtime_r(&now, &tm);
else
localtime_r(&now, &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") || !strcmp(sp, "DATE_UTC")) {
now = time(NULL);
if(strcmp(sp, "DATE_UTC") == 0)
now -= xpTimeZone_local() * 60;
return datestr(now);
if(strncmp(sp, "DATE:", 5) == 0 || strncmp(sp, "TIME:", 5) == 0) {

Rob Swindell
committed
SAFECOPY(tmp, sp + 5);
c_unescape_str(tmp);
now = time(NULL);
memset(&tm, 0, sizeof(tm));
localtime_r(&now, &tm);

Rob Swindell
committed
strftime(str, maxlen, tmp, &tm);
return str;
}
if(strncmp(sp, "UTC:", 4) == 0) {
SAFECOPY(tmp, sp + 4);
c_unescape_str(tmp);
now = time(NULL);
memset(&tm, 0, sizeof(tm));
gmtime_r(&now, &tm);
strftime(str, maxlen, tmp, &tm);
return str;
}
if(!strcmp(sp,"DATETIME"))
return(timestr(time(NULL)));
if(!strcmp(sp,"DATETIME_UTC"))
return timestr(time(NULL) - (xpTimeZone_local() * 60));
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 date_format(&cfg, str, maxlen);
if(strcmp(sp, "BDATEFMT") == 0 || strcmp(sp, "BIRTHFMT") == 0) {
return birthdate_format(&cfg, str, maxlen);
if(strcmp(sp, "GENDERS") == 0)
return cfg.new_genders;
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, "%u", getfilecount(path));
}
if(strcmp(sp, "FILES") == 0) { // Number of files in current directory
safe_snprintf(str, maxlen, "%u", getfiles(&cfg, usrdir[curlib][curdir[curlib]]));
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
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,"%u", stats.logons);
if(!strcmp(sp,"PREVON") || !strcmp(sp,"LASTCALLERNODE")
|| !strcmp(sp,"LASTCALLERSYSTEM"))

Rob Swindell
committed
if(strcmp(sp, "GETDIM") == 0) {

Rob Swindell
committed
getdimensions();

Rob Swindell
committed
return nulstr;
}
if(strcmp(sp, "GETKEY") == 0) {
getkey();
return(nulstr);
}
if(strcmp(sp, "CONTINUE") == 0) {
char ch = getkey(K_UPPER);
if(ch == no_key() || ch == quit_key())
if(strncmp(sp, "WAIT:", 5) == 0) {
if(!strcmp(sp,"PAUSE") || !strcmp(sp,"MORE")) {
lncntr=0;
if(!strcmp(sp,"NOPAUSE") || !strcmp(sp,"POFF")) {
if(!strcmp(sp,"PON") || !strcmp(sp,"AUTOMORE")) {

Rob Swindell
committed
SAFECOPY(tmp, sp + 5);
int margin = centered ? column : 1;
if(margin < 1) margin = 1;

Rob Swindell
committed
c_unescape_str(tmp);
while(*tmp && online && column < cols - margin)
bputs(tmp, P_TRUNCATE);
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", yes_key());
return str;
}
if(strcmp(sp, "NOCHAR") == 0) { // PCBoard
safe_snprintf(str, maxlen, "%c", no_key());
return str;
}
if(strcmp(sp, "QUITCHAR") == 0) {
safe_snprintf(str, maxlen, "%c", quit_key());