pkgsrc-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[pkgsrc/trunk]: pkgsrc/net Update xymon and xymonclient to version 4.3.29.
details: https://anonhg.NetBSD.org/pkgsrc/rev/7649af0b1093
branches: trunk
changeset: 344688:7649af0b1093
user: spz <spz%pkgsrc.org@localhost>
date: Sun Nov 24 20:16:55 2019 +0000
description:
Update xymon and xymonclient to version 4.3.29.
Add patches to xymon from the xymon code repository to fix compatibility
issues in 4.3.29.
Upstream changelog:
Changes for 4.3.29
==================
Several buffer overflow security issues have been resolved, as well as
a potential XSS attack on certain CGI interfaces. Although the ability
to exploit is limited, all users are urged to upgrade.
The assigned CVE numbers are:
CVE-2019-13451, CVE-2019-13452, CVE-2019-13455, CVE-2019-13473,
CVE-2019-13474, CVE-2019-13484, CVE-2019-13485, CVE-2019-13486
In addition, revisions have been made to a number of places throughout
the code to convert the most common sprintf statements to snprintf for
safer processing, which should reduce the impact of similar parsing.
Additional work on this will continue in the future.
The affected CGIs are:
history.c (overflow of histlogfn) = CVE-2019-13451
reportlog.c (overflow of histlogfn) = CVE-2019-13452
csvinfo.c (overflow of dbfn) = CVE-2019-13273
csvinfo.c (reflected XSS) = CVE-2019-13274
acknowledge.c (overflow of msgline) = CVE-2019-13455
appfeed.c (overflow of errtxt) = CVE-2019-13484
history.c (overflow of selfurl) = CVE-2019-13485
svcstatus.c (overflow of errtxt) = CVE-2019-13486
We would like to thank the University of Cambridge Computer Security
Incident Response Team for their assistance in reporting and helping
resolve these issues.
Additional Changes:
On Linux, a few additional tmpfs volumes are ignored by default
on new (or unmodified) installs. This includes /run/user/<uid>,
which is a transient, per-session tmpfs on some systems. To re-
enable monitoring for this (if you are running services under
a user with a login session), you may need to edit the analysis.cfg(5)
file.
After upgrade, these partitions will no longer be alerted on or
tracked, and their associated RRD files may also be removed:
/run/user/<uid> (but NOT /run)
/dev (but NOT /dev/shm)
/sys/fs/cgroup
/lib/init/rw
The default hard limit for an incoming message has been raised from
10MB to 64MB
The secure apache config snippet no longer requires a xymongroups file
to be present (and module loaded), since it's not used by default. This
will not affect existing installs.
A --no-cpu-listing option has been added to xymond_client to suppress the
'top' output in cpu test status messages.
The conversation used in SMTP checks has been adjusted to perform a proper
"EHLO" greeting against servers, using the host string 'xymonnet'. If the
string needs to be adjusted, however, see protocols.cfg(5)
"Actual" memory usage (as a percentage) may be >100% on some platforms
in certain situations. This alone will not be tagged as "invalid" data
and should be graphed in RRD.
diffstat:
net/xymon/Makefile | 6 +-
net/xymon/distinfo | 29 ++-
net/xymon/patches/patch-build_Makefile.Linux | 28 +-
net/xymon/patches/patch-lib_acklog.c | 22 ++
net/xymon/patches/patch-lib_availability.c | 200 +++++++++++++++++++
net/xymon/patches/patch-lib_availability.h | 15 +
net/xymon/patches/patch-lib_eventlog.c | 22 ++
net/xymon/patches/patch-lib_holidays.c | 22 ++
net/xymon/patches/patch-lib_htmllog.c | 29 ++
net/xymon/patches/patch-lib_misc.c | 18 +
net/xymon/patches/patch-lib_stackio.c | 22 ++
net/xymon/patches/patch-lib_timefunc.c | 22 ++
net/xymon/patches/patch-lib_tree.c | 27 ++
net/xymon/patches/patch-web_history.c | 16 +
net/xymon/patches/patch-web_reportlog.c | 31 ++
net/xymon/patches/patch-web_showgraph.c | 20 +
net/xymon/patches/patch-xymond_combostatus.c | 15 +
net/xymon/patches/patch-xymond_rrd_do__temperature.c | 59 +++++
net/xymon/patches/patch-xymond_xymond__history.c | 20 +
net/xymon/patches/patch-xymonnet_xymonnet.c | 58 +++++
net/xymonclient/Makefile | 6 +-
net/xymonclient/distinfo | 12 +-
net/xymonclient/patches/patch-build_Makefile.Linux | 28 +-
23 files changed, 685 insertions(+), 42 deletions(-)
diffs (truncated from 876 to 300 lines):
diff -r 4df693353d95 -r 7649af0b1093 net/xymon/Makefile
--- a/net/xymon/Makefile Sun Nov 24 19:42:58 2019 +0000
+++ b/net/xymon/Makefile Sun Nov 24 20:16:55 2019 +0000
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile,v 1.56 2018/11/14 22:22:15 kleink Exp $
+# $NetBSD: Makefile,v 1.57 2019/11/24 20:16:55 spz Exp $
#
-DISTNAME= xymon-4.3.28
-PKGREVISION= 4
+DISTNAME= xymon-4.3.29
+#PKGREVISION= 0
CATEGORIES= net
MASTER_SITES= ${MASTER_SITE_SOURCEFORGE:=xymon/}
diff -r 4df693353d95 -r 7649af0b1093 net/xymon/distinfo
--- a/net/xymon/distinfo Sun Nov 24 19:42:58 2019 +0000
+++ b/net/xymon/distinfo Sun Nov 24 20:16:55 2019 +0000
@@ -1,9 +1,9 @@
-$NetBSD: distinfo,v 1.17 2017/09/28 10:40:35 spz Exp $
+$NetBSD: distinfo,v 1.18 2019/11/24 20:16:55 spz Exp $
-SHA1 (xymon-4.3.28.tar.gz) = 9b134af41549e46f46f310b315f70ce42e6668a7
-RMD160 (xymon-4.3.28.tar.gz) = 7d2426a6639c52b0a1f6e3d2e5c4e4607090809d
-SHA512 (xymon-4.3.28.tar.gz) = 589230ee05028c2131d1ddf32dd1a5f302bfcdbf8276bc6ee0fb9590ae2bfe218bf49d931cfa68491160c35818d0bee93b7fcea47b85f924a4f991a5ff608477
-Size (xymon-4.3.28.tar.gz) = 3966200 bytes
+SHA1 (xymon-4.3.29.tar.gz) = faf18c75839b4ec0863cbf309651c54bb2890988
+RMD160 (xymon-4.3.29.tar.gz) = 5a1bac0ae5674db6e3d810a25597373fdc6b7238
+SHA512 (xymon-4.3.29.tar.gz) = 63db006baa0cf0a4e3b85d2cbe0a6e230f87922d0b9cc21792672a1551d40f60ea371a34337a93df248456731709a91bafdb630a219a25ba9d76043e54ded196
+Size (xymon-4.3.29.tar.gz) = 3548283 bytes
SHA1 (patch-aa) = 227b631c6e002712ebf6019d8473ca4b44904e4a
SHA1 (patch-ab) = 39a6af51ec216bb8cbdb57a3c07d82fce559b27f
SHA1 (patch-ac) = 518abacafb7f082ab2de6bcaace27d3e3d4de633
@@ -16,7 +16,7 @@
SHA1 (patch-build_Makefile.FreeBSD) = 6ebfa5bab2955eaa42b0021de085eb7ba536432b
SHA1 (patch-build_Makefile.HP-UX) = bdd713b83f3670096bb10def6c59036d0a4aa377
SHA1 (patch-build_Makefile.IRIX) = b0ce34295d199ffd1e9008569667abbe436a2355
-SHA1 (patch-build_Makefile.Linux) = 3dd75b6613fbf268411ec177f8be5acd48ac8c27
+SHA1 (patch-build_Makefile.Linux) = bddfea6c8400fdd7d8a83a6958f1e4139ef988b6
SHA1 (patch-build_Makefile.OSF1) = 1a7afce4beeef249b2435c2ef14f45b2c2dbf8a2
SHA1 (patch-build_Makefile.OSX) = a72b748600b043f458452ab37175c38087375559
SHA1 (patch-build_Makefile.OpenBSD) = cf40c7839ba6290d349328e2e01a20bdaf274fc6
@@ -26,8 +26,25 @@
SHA1 (patch-build_snmp.sh) = 4141c6e2bebea078ac662b7585e579f2af8ee64f
SHA1 (patch-common_Makefile) = 32b7da06cd9d22f98ee0f83bb36ed6441c066707
SHA1 (patch-configure) = 3754b9056c365b8664e5fc9620b17c4e13453b2e
+SHA1 (patch-lib_acklog.c) = 053e63b7b5d55345360c49279eacc7ae470cc3a4
+SHA1 (patch-lib_availability.c) = 04d6133f00811afd1aa1263a00ae6396df5202e3
+SHA1 (patch-lib_availability.h) = 89ac49779c9bd5090718dfdc24949c6eb67b5705
+SHA1 (patch-lib_eventlog.c) = b1b8ee4ffb211f2461cc3d6e3055d9ee045a4da0
+SHA1 (patch-lib_holidays.c) = 980d42b5780e37a483fde6a2059294e050abba85
+SHA1 (patch-lib_htmllog.c) = 7184ec5014f9b19916541b5ac4c7b7f393623a4d
+SHA1 (patch-lib_misc.c) = 2ee78934dfb5c25f78fc9c5400baadd3e2e7b70b
+SHA1 (patch-lib_stackio.c) = 6e97fde074ce41b39c29bf280c560b01d885f875
+SHA1 (patch-lib_timefunc.c) = 7e7d7e17252a8ea2e4b7d5bd8e5c2fa7247b9287
+SHA1 (patch-lib_tree.c) = 13f8d0d89cb0e0cb9e023734b60f9d67707b0a99
SHA1 (patch-web_Makefile) = a27fbb7e97ce0c2f30093d5b05b0af2708fb594b
+SHA1 (patch-web_history.c) = cdddc0230efdb79dbae3055a93e252f43dc49524
+SHA1 (patch-web_reportlog.c) = 78068e40253ab295dced37368f19bf1bbe5bd747
+SHA1 (patch-web_showgraph.c) = 9c5542975ffd65aff9d2fd03a3d63fde10648ad4
SHA1 (patch-xymond_client_netbsd.c) = 9034777cbf12e3e168cf1598bfd444468e3a5086
+SHA1 (patch-xymond_combostatus.c) = cce34cc01bfaba9f171e7d90d3ec398a97e4c4d5
SHA1 (patch-xymond_rrd_do__disk.c) = e72cb0364e4e949e02a045da0abca46083624253
+SHA1 (patch-xymond_rrd_do__temperature.c) = bf78c81b6f189e6424574eae53921cf44d653a0d
SHA1 (patch-xymond_rrd_do__vmstat.c) = 8062acc24e9b0e767c5abd3373641aa7b9a5b2ae
+SHA1 (patch-xymond_xymond__history.c) = 4fadebc1caaba9a0368de7626ed389040718d1ac
+SHA1 (patch-xymonnet_xymonnet.c) = 849cb3c3f3e673dc3927ce34195f9bc6c594d895
SHA1 (patch-xymonproxy_Makefile) = 8ecfa4ceb66f66b7d5f40c01339479b26865746e
diff -r 4df693353d95 -r 7649af0b1093 net/xymon/patches/patch-build_Makefile.Linux
--- a/net/xymon/patches/patch-build_Makefile.Linux Sun Nov 24 19:42:58 2019 +0000
+++ b/net/xymon/patches/patch-build_Makefile.Linux Sun Nov 24 20:16:55 2019 +0000
@@ -1,22 +1,24 @@
-$NetBSD: patch-build_Makefile.Linux,v 1.2 2017/09/28 10:40:35 spz Exp $
+$NetBSD: patch-build_Makefile.Linux,v 1.3 2019/11/24 20:16:55 spz Exp $
---- build/Makefile.Linux.orig 2012-07-23 11:29:13.000000000 +0000
+--- build/Makefile.Linux.orig 2019-03-11 23:17:41.000000000 +0000
+++ build/Makefile.Linux
-@@ -6,12 +6,15 @@ OSDEF = -DLINUX
- NETLIBS =
+@@ -5,13 +5,17 @@ OSDEF = -DLINUX
+ # NETLIBS: Use replacement rpc
+ NETLIBS = -ltirpc
++# pkgsrcification
++PKGDIR ?= /usr/pkg
++PKGDEF = -I${PKGDIR}/include -L${PKGDIR}/lib -Wl,--rpath=${PKGDIR}/lib
++
# Compile flags for normal build
-+PKGDIR?=/usr/pkg
CC = gcc
- GCCVER := $(shell gcc -dumpversion|cut -d. -f1)
- ifeq ($(GCCVER),4)
-- CFLAGS = -g -O2 -Wall -Wno-unused -Wno-pointer-sign -D_REENTRANT $(LFSDEF) $(OSDEF)
-+ CFLAGS += -g -O2 -Wall -Wno-unused -Wno-pointer-sign -D_REENTRANT $(LFSDEF) $(OSDEF) \
-+ -I${PKGDIR}/include -L${PKGDIR}/lib -Wl,--rpath=${PKGDIR}/lib
+ GCCVER := $(shell test 0`gcc -dumpversion|cut -d. -f1` -ge 4 && echo yes)
+ ifeq ($(GCCVER),yes)
+- CFLAGS = -g -O2 -Wall -Wno-unused -I/usr/include/tirpc -Wno-pointer-sign -D_REENTRANT $(LFSDEF) $(OSDEF)
++ CFLAGS += -g -O2 -Wall -Wno-unused -I/usr/include/tirpc -Wno-pointer-sign -D_REENTRANT $(LFSDEF) $(OSDEF) $(PKGDEF)
else
-- CFLAGS = -g -O2 -Wall -Wno-unused -D_REENTRANT $(LFSDEF) $(OSDEF)
-+ CFLAGS += -g -O2 -Wall -Wno-unused -D_REENTRANT $(LFSDEF) $(OSDEF) \
-+ -I${PKGDIR}/include -L${PKGDIR}/lib -Wl,--rpath=${PKGDIR}/lib
+- CFLAGS = -g -O2 -Wall -Wno-unused -I/usr/include/tirpc -D_REENTRANT $(LFSDEF) $(OSDEF)
++ CFLAGS += -g -O2 -Wall -Wno-unused -I/usr/include/tirpc -D_REENTRANT $(LFSDEF) $(OSDEF) $(PKGDEF)
endif
ifndef PKGBUILD
diff -r 4df693353d95 -r 7649af0b1093 net/xymon/patches/patch-lib_acklog.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/net/xymon/patches/patch-lib_acklog.c Sun Nov 24 20:16:55 2019 +0000
@@ -0,0 +1,22 @@
+$NetBSD: patch-lib_acklog.c,v 1.1 2019/11/24 20:16:55 spz Exp $
+
+from https://sourceforge.net/p/xymon/code/8084/
+Add guards around GCC diagnostics pragma to allow for building on older vers
+
+--- lib/acklog.c.orig 2019-07-23 14:46:51.000000000 +0000
++++ lib/acklog.c
+@@ -126,10 +126,14 @@ void do_acklog(FILE *output, int maxcoun
+ /* Show only the first 30 characters in message */
+ if (strlen(ackmsg) > 30) ackmsg[30] = '\0';
+
++#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wformat-truncation"
++#endif // __GNUC__
+ snprintf(ackfn, sizeof(ackfn), "%s/ack.%s", xgetenv("XYMONACKDIR"), hosttest);
++#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+ #pragma GCC diagnostic pop
++#endif // __GNUC__
+
+ testname = strrchr(hosttest, '.');
+ if (testname) {
diff -r 4df693353d95 -r 7649af0b1093 net/xymon/patches/patch-lib_availability.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/net/xymon/patches/patch-lib_availability.c Sun Nov 24 20:16:55 2019 +0000
@@ -0,0 +1,200 @@
+$NetBSD: patch-lib_availability.c,v 1.1 2019/11/24 20:16:55 spz Exp $
+
+from https://sourceforge.net/p/xymon/code/8081/
+Fix assorted crashes with xymongen report generation after string changes
+
+--- lib/availability.c.orig 2019-07-23 14:46:51.000000000 +0000
++++ lib/availability.c
+@@ -31,6 +31,7 @@ static int reptimecnt = 0;
+
+ replog_t *reploghead = NULL;
+
++/* TODO: This logic differs from elsewhere below */
+ char *durationstr(time_t duration)
+ {
+ static char dur[100];
+@@ -42,13 +43,13 @@ char *durationstr(time_t duration)
+ else {
+ dur[0] = '\0';
+ if (duration > 86400) {
+- snprintf(dhelp, sizeof(dhelp), "%u days ", (unsigned int)(duration / 86400));
++ snprintf(dhelp, 100, "%u days ", (unsigned int)(duration / 86400));
+ duration %= 86400;
+- strncpy(dur, dhelp, sizeof(dur));
++ strncpy(dur, dhelp, 100);
+ }
+- snprintf(dhelp, sizeof(dhelp), "%u:%02u:%02u", (unsigned int)(duration / 3600),
++ snprintf(dhelp, 100, "%u:%02u:%02u", (unsigned int)(duration / 3600),
+ (unsigned int)((duration % 3600) / 60), (unsigned int)(duration % 60));
+- strncat(dur, dhelp, (sizeof(dur) - strlen(dur)));
++ strncat(dur, dhelp, (100 - strlen(dur)));
+ }
+
+ return dur;
+@@ -162,21 +163,21 @@ static char *parse_histlogfile(char *hos
+
+ cause[0] = '\0';
+
+- snprintf(fn, sizeof(fn), "%s/%s", xgetenv("XYMONHISTLOGS"), commafy(hostname));
++ snprintf(fn, PATH_MAX, "%s/%s", xgetenv("XYMONHISTLOGS"), commafy(hostname));
+ for (p = strrchr(fn, '/'); (*p); p++) if (*p == ',') *p = '_';
+- snprintf(p, (sizeof(fn) - (p - fn)), "/%s/%s", servicename, timespec);
++ snprintf(p, (PATH_MAX - (p - fn)), "/%s/%s", servicename, timespec);
+
+ dbgprintf("Looking at history logfile %s\n", fn);
+ fd = fopen(fn, "r");
+ if (fd != NULL) {
+- while (!causefull && fgets(l, sizeof(l), fd)) {
++ while (!causefull && fgets(l, MAX_LINE_LEN, fd)) {
+ p = strchr(l, '\n'); if (p) *p = '\0';
+
+ if ((l[0] == '&') && (strncmp(l, "&green", 6) != 0)) {
+ p = skipwhitespace(skipword(l));
+- if ((strlen(cause) + strlen(p) + strlen("<BR>\n") + 1) < sizeof(cause)) {
+- strncat(cause, p, (sizeof(cause) - strlen(cause)));
+- strncat(cause, "<BR>\n", (sizeof(cause) - strlen(cause)));
++ if ((strlen(cause) + strlen(p) + strlen("<BR>\n") + 1) < MAX_LINE_LEN) {
++ strncat(cause, p, (MAX_LINE_LEN - strlen(cause)));
++ strncat(cause, "<BR>\n", (MAX_LINE_LEN - strlen(cause)));
+ }
+ else causefull = 1;
+ }
+@@ -184,7 +185,7 @@ static char *parse_histlogfile(char *hos
+
+ #if 1
+ if (strlen(cause) == 0) {
+- strncpy(cause, "See detailed log", sizeof(cause));
++ strncpy(cause, "See detailed log", MAX_LINE_LEN);
+ }
+ #else
+ /* What is this code supposed to do ? The sscanf seemingly never succeeds */
+@@ -192,28 +193,28 @@ static char *parse_histlogfile(char *hos
+ if (strlen(cause) == 0) {
+ int offset;
+ rewind(fd);
+- if (fgets(l, sizeof(l), fd)) {
++ if (fgets(l, MAX_LINE_LEN, fd)) {
+ p = strchr(l, '\n'); if (p) *p = '\0';
+ if (sscanf(l, "%*s %*s %*s %*s %*s %*s %*s %n", &offset) == 1) {
+- strncpy(cause, l+offset, sizeof(cause));
++ strncpy(cause, l+offset, MAX_LINE_LEN);
+ }
+ else {
+ errprintf("Scan of file %s failed, l='%s'\n", fn, l);
+ }
+- cause[sizeof(cause)-1] = '\0';
++ cause[MAX_LINE_LEN-1] = '\0';
+ }
+ }
+ #endif
+
+ if (causefull) {
+- cause[sizeof(cause) - strlen(" [Truncated]") - 1] = '\0';
+- strncat(cause, " [Truncated]", (sizeof(cause) - strlen(cause)));
++ cause[MAX_LINE_LEN - strlen(" [Truncated]") - 1] = '\0';
++ strncat(cause, " [Truncated]", (MAX_LINE_LEN - strlen(cause)));
+ }
+
+ fclose(fd);
+ }
+ else {
+- strncpy(cause, "No historical status available", sizeof(cause));
++ strncpy(cause, "No historical status available", MAX_LINE_LEN);
+ }
+
+ return strdup(cause);
+@@ -358,7 +359,7 @@ static char *timename(char *timestring)
+
+ if (tokens[4]) {
+ /* Got all 5 elements */
+- snprintf(timespec, sizeof(timespec), "%s_%s_%s_%s_%s",
++ snprintf(timespec, 25, "%s_%s_%s_%s_%s",
+ tokens[0], tokens[1], tokens[2], tokens[3], tokens[4]);
+ }
+ else {
+@@ -404,17 +405,17 @@ int parse_historyfile(FILE *fd, reportin
+ /* If for_history and fromtime is 0, don't do any seeking */
+ if (!for_history || (fromtime > 0)) {
+ fileerrors = scan_historyfile(fd, fromtime, totime,
+- l, sizeof(l), &starttime, &duration, colstr, sizeof(colstr));
++ l, MAX_LINE_LEN, &starttime, &duration, colstr, MAX_LINE_LEN);
+ }
+ else {
+ /* Already positioned (probably in a pipe) */
+- if (get_historyline(l, sizeof(l), fd, &fileerrors, colstr, &uistart, &uidur, &scanres)) {
++ if (get_historyline(l, MAX_LINE_LEN, fd, &fileerrors, colstr, &uistart, &uidur, &scanres)) {
+ starttime = uistart; duration = uidur;
+ if (scanres == 2) duration = getcurrenttime(NULL) - starttime;
+ }
+ else {
+ starttime = getcurrenttime(NULL); duration = 0;
+- strncpy(colstr, "clear", sizeof(colstr));
++ strncpy(colstr, "clear", MAX_LINE_LEN);
+ fileerrors = 1;
+ }
+ }
+@@ -437,7 +438,7 @@ int parse_historyfile(FILE *fd, reportin
+ do {
+ /* If event ends after our reportend, adjust duration */
+ if ((starttime + duration) > totime) duration = (totime - starttime);
+- strncat(colstr, " ", (sizeof(colstr) - strlen(colstr))); color = parse_color(colstr);
++ strncat(colstr, " ", (MAX_LINE_LEN - strlen(colstr))); color = parse_color(colstr);
+
+ if (color != -1) {
+ unsigned long sladuration = 0;
+@@ -474,7 +475,7 @@ int parse_historyfile(FILE *fd, reportin
+ }
+
+ if ((starttime + duration) < totime) {
+- if (get_historyline(l, sizeof(l), fd, &fileerrors, colstr, &uistart, &uidur, &scanres)) {
++ if (get_historyline(l, MAX_LINE_LEN, fd, &fileerrors, colstr, &uistart, &uidur, &scanres)) {
+ starttime = uistart; duration = uidur;
+ if (scanres == 2) duration = getcurrenttime(NULL) - starttime;
+ }
+@@ -560,9 +561,9 @@ int history_color(FILE *fd, time_t snaps
+ char *p;
+
+ *histlogname = NULL;
+- scan_historyfile(fd, snapshot, snapshot, l, sizeof(l), starttime, &duration, colstr, sizeof(colstr));
++ scan_historyfile(fd, snapshot, snapshot, l, MAX_LINE_LEN, starttime, &duration, colstr, MAX_LINE_LEN);
+
+- strncat(colstr, " ", (sizeof(colstr) - strlen(colstr)));
Home |
Main Index |
Thread Index |
Old Index