xymon

Check-in [c5d1193e11]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge 4.3.11 fixes/enhancements to trunk git-svn-id: http://svn.code.sf.net/p/xymon/code/trunk@7191 44351d6e-118b-4698-b696-ce33095ecaa4
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | master
Files: files | file ages | folders
SHA3-256: c5d1193e111cb13dbe505a8216c06780ed049f0f12fc568237ead34e264a8a4d
User & Date: storner@users.sf.net 2013-04-22 08:11:39
Context
2013-04-22
08:18
Merge 4.3.11 Makefile fixes to trunk git-svn-id: http://svn.code.sf.net/p/xymon/code/trunk@7192 44351d6e-118b-4698-b696-ce33095ecaa4 check-in: 0602bf9dee user: storner@users.sf.net tags: trunk, master
08:11
Merge 4.3.11 fixes/enhancements to trunk git-svn-id: http://svn.code.sf.net/p/xymon/code/trunk@7191 44351d6e-118b-4698-b696-ce33095ecaa4 check-in: c5d1193e11 user: storner@users.sf.net tags: trunk, master
2012-11-30
06:22
FreeBSD client: Memory patch for FreeBSD 8.0+, from Mark Felder git-svn-id: http://svn.code.sf.net/p/xymon/code/trunk@7175 44351d6e-118b-4698-b696-ce33095ecaa4 check-in: e47e615f01 user: storner@users.sf.net tags: trunk, master
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Changes.

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16











































































17
18
19
20
21
22
23
Changes from 4.3.7 -> 4.4.0
=========================================
* rev ????
* Change all network I/O to support IPv6 as well as IPv4

* Enable SSL-encryption of traffic between Xymon components
* Fix build on systems with SSLv2 disabled in SSL library
* Fix configure-script on systems with unusual default library location
* BBNUMERIC is no longer passed to alert scripts, the format is 
  incompatible with IPv6 adresses.
* MACHIP in alert script now contains the regular (dotted IPv4)
  address, e.g. "10.1.2.3" instead of "010001002003", or the
  regular IPv6 address.
* protocols.cfg has a new syntax for EXPECT/SEND dialog
* Network tests support SSL-encrypted protocols using STARTTLS
* xymonnet re-worked and split up into smaller modules
* Support for NTP tests in xymonnet (no longer needs ntpdate)












































































Changes from 4.3.6 -> 4.3.7 (13 Dec 2011)
=========================================
* rev 6803
* Fix acknowledge CGI (broken in 4.3.6)
* Fix broken uptime calculation for systems reporting "1 day"
* Workaround Solaris breakage in the LFS-support detection
|
|
|
<
>
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3

4
5
6
7
8
9
10
11
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
46
47
48
49
50
51
52
53
54
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
Changes from 4.3.10 -> 4.3.11 (21 Apr 2013)
===========================================
* rev 7188


* Fix wrong file permissions when installing
* Linux client: Fix handling of root filesystem when mounted on "/dev/root"
* trends webpage: Fix case where hostname disappears after zoom.
* FreeBSD client: Memory patch for FreeBSD 8.0+
* xymond_alert: Fix problem with UNMATCHED rules triggering when there are
  actual recipients, but their alerts are suppressed due to a REPEAT
  setting not having expired.
* xymond_rrd: Dont crash if called with an empty status/data message
* xymond_channel: Report cause when channel-child exits/crashes
* xymongen: Geneate an overview page with only reds (like non-green)
* xymongen: Optionally define env. variable BOARDFILTER to select
  hosts/tests included in the generated pages
* links: Add pdf, docx and odt as known document formats
* Fix potential crashes after an alert cookie expired
* Fix potential crash after deleting/renaming a host
* Speedup loading of the hosts.cfg file, noticeable with very
  large hosts.cfg files (100.000+ hosts)

Changes from 4.3.9 -> 4.3.10 (6 Aug 2012)
=========================================
* rev 7164

* Fix build problems with "errno"
* Fix build problems with OpenSSL in non-default locations
* Fix build problems with certain LDAP configurations
* Fix build problems with RRDtool on FreeBSD / OpenBSD
* Fix problem with ifstat data from Fedora in graphs
* "inode" check on FreeBSD, OpenBSD, OSX, Solaris, HP/UX, AIX
  in addition to existing support for Linux
* Document building and installing Xymon on common platforms 
  (Linux, FreeBSD, OpenBSD, Solaris)
* Enhance xymoncfg so it can be used to import Xymon configuration
  settings into shell-scripts.

Changes from 4.3.8 -> 4.3.9 (15 Jul 2012)
=========================================
* rev 7120

* Fix crash when XYMSRV is undefined but XYMSERVERS is
* Fix error in calculating combo-status messages with
  forward references
* Fix error in disable-until-TIME or disable-until-OK code
* Fix documentation of DURATION in alerts.cfg / xymond_alert so
  it is consistenly listed as being in "minutes". 
* Permit explicit use of ">" and ">=" in alerts.cfg
* Permit building without the RRDtool libraries, e.g. for
  a network-tester build, but with trend-graphing disabled.
* Full compiler-warning cleanup
* Various configuration/build-script issues fixed.

Changes from 4.3.7 -> 4.3.8 (15 Jul 2012)
=========================================
* rev 7082

Bugfixes
* Workaround for DNS timeout handling, now fixed at approximately 25
  seconds.
* "hostinfo" command for xymond documented
* confreport only shows processes that are monitored
* analysis.cfg parsing of COLOR for UP rules was broken
* RRD handlers no longer crash after receiving 1 billion updates
* Using .netrc for authentication could crash xymonnet
* "directory" includes would report the wrong filename for missing
  directories.
* useradm CGI would invoke htpassword twice
* "include" and "directory" now ignores trailing whitespace
* SSLv2 support disabled if SSL-library does not support it
* Minor bugfixes and cleanups of compiler warnings.

Enhancements
* Service status on info page now links to the detailed status page.
* Add RRDGRAPHOPTS setting to permit global user-specified RRD options,
  e.g. for font to showgraph CGI
* Add check for the size of public keys used in SSL certificates
  (enabled via --sslkeysize=N option for xymonnet)
* Optionally disable the display of SSL ciphers in the sslcert status
  (the --no-cipherlist option for xymonnet)
* Improved build-scripts works on newer systems with libraries in
  new and surprising places
* Reduce xymonnet memory usage and runtime for ping tests when there
  are multiple hosts.cfg entries with the same IP-address.
* Add code for inode-monitoring on Linux. Does not currently work on
  any other client platform.
* Added the ability to disable tests until a specific time, instead of
  for some interval. Disabling a test also now computes the expire time
  for the disable to happen at the next closest minute.


Changes from 4.3.6 -> 4.3.7 (13 Dec 2011)
=========================================
* rev 6803
* Fix acknowledge CGI (broken in 4.3.6)
* Fix broken uptime calculation for systems reporting "1 day"
* Workaround Solaris breakage in the LFS-support detection

Changes to build/Makefile.Linux.

17
18
19
20
21
22
23





24
25
26
27
28
29
30
31
32
ifndef PKGBUILD
RPATH = -Wl,--rpath,
endif

# Compile flags for debugging
# CFLAGS = -g -DDEBUG -Wall -D_REENTRANT $(LFSDEF) $(OSDEF)






# By default, Xymon uses a static library for common code.
# To save some diskspace and run-time memory, you can use a
# shared library by un-commenting this.
# XYMONLIBRARY=libxymon.so

# Mail program: This must support "CMD -s SUBJECT ADDRESS" to send out a mail with a subject
# Typically, this will be "mail" or "mailx"
MAILPROGRAM="mail"








>
>
>
>
>









17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
ifndef PKGBUILD
RPATH = -Wl,--rpath,
endif

# Compile flags for debugging
# CFLAGS = -g -DDEBUG -Wall -D_REENTRANT $(LFSDEF) $(OSDEF)

# For profiling
# CFLAGS = -g -pg -Wall -D_REENTRANT $(LFSDEF) $(OSDEF)
# Note: Do 'export GMON_OUT_PREFIX=/var/tmp/FILENAME' to save profiling output in /var/tmp
# Use gprof to analyse

# By default, Xymon uses a static library for common code.
# To save some diskspace and run-time memory, you can use a
# shared library by un-commenting this.
# XYMONLIBRARY=libxymon.so

# Mail program: This must support "CMD -s SUBJECT ADDRESS" to send out a mail with a subject
# Typically, this will be "mail" or "mailx"
MAILPROGRAM="mail"

Changes to client/xymonclient-linux.sh.

41
42
43
44
45
46
47
48

49
50
51
52





53
54
55
56
57
58
59
	cat /etc/arch-release
fi
echo "[uptime]"
uptime
echo "[who]"
who
echo "[df]"
EXCLUDES=`cat /proc/filesystems | grep nodev | awk '{print $2}' | xargs echo | sed -e 's! ! -x !g'`

df -Pl -x iso9660 -x $EXCLUDES | sed -e '/^[^ 	][^ 	]*$/{
N
s/[ 	]*\n[ 	]*/ /
}'





echo "[mount]"
mount
echo "[free]"
free
echo "[ifconfig]"
/sbin/ifconfig
echo "[route]"







|
>



|
>
>
>
>
>







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
	cat /etc/arch-release
fi
echo "[uptime]"
uptime
echo "[who]"
who
echo "[df]"
EXCLUDES=`cat /proc/filesystems | grep nodev | grep -v rootfs | awk '{print $2}' | xargs echo | sed -e 's! ! -x !g'`
ROOTFS=`readlink -m /dev/root`
df -Pl -x iso9660 -x $EXCLUDES | sed -e '/^[^ 	][^ 	]*$/{
N
s/[ 	]*\n[ 	]*/ /
}' -e "s&^rootfs&${ROOTFS}&"
echo "[inode]"
df -Pil -x iso9660 -x $EXCLUDES | sed -e '/^[^ 	][^ 	]*$/{
N
s/[ 	]*\n[ 	]*/ /
}' -e "s&^rootfs&${ROOTFS}&"
echo "[mount]"
mount
echo "[free]"
free
echo "[ifconfig]"
/sbin/ifconfig
echo "[route]"

Changes to debian/changelog.

1
2
3
4
5















6


















7

























































8
9
10
11
12
13
14
xymon (4.3.7.20120107.ip6ssl) unstable; urgency=low

   * rev 6867
   * IPv6 support for xymond + sendmsg()
   * SSL support for xymond + sendmsg()


































 -- Henrik Stoerner <henrik@hswn.dk>  Sat, 07 Jan 2012 18:00:00 +0100


























































xymon (4.3.7) unstable; urgency=low

   * rev 6803
   * Fix acknowledge CGI (broken in 4.3.6)
   * Fix broken uptime calculation for systems reporting "1 day"
   * Workaround Solaris breakage in the LFS-support detection
|

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
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
46
47
48
49
50
51
52
53
54
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
xymon (4.3.11) unstable; urgency=low

   * rev 7188
   * Fix wrong file permissions when installing
   * Linux client: Fix handling of root filesystem when mounted on "/dev/root"
   * trends webpage: Fix case where hostname disappears after zoom.
   * FreeBSD client: Memory patch for FreeBSD 8.0+
   * xymond_alert: Fix problem with UNMATCHED rules triggering when there are
     actual recipients, but their alerts are suppressed due to a REPEAT
     setting not having expired.
   * xymond_rrd: Dont crash if called with an empty status/data message
   * xymond_channel: Report cause when channel-child exits/crashes
   * xymongen: Geneate an overview page with only reds (like non-green)
   * xymongen: Optionally define env. variable BOARDFILTER to select
     hosts/tests included in the generated pages
   * links: Add pdf, docx and odt as known document formats
   * Fix potential crashes after an alert cookie expired
   * Fix potential crash after deleting/renaming a host
   * Speedup loading of the hosts.cfg file, noticeable with very
     large hosts.cfg files (100.000+ hosts)

 -- Henrik Stoerner <henrik@hswn.dk>  Sun, 21 Apr 2013 15:24:01 +0200

xymon (4.3.10) unstable; urgency=low

   * rev 7164

   * Fix build problems with "errno"
   * Fix build problems with OpenSSL in non-default locations
   * Fix build problems with certain LDAP configurations
   * Fix build problems with RRDtool on FreeBSD / OpenBSD
   * Fix problem with ifstat data from Fedora in graphs
   * "inode" check on FreeBSD, OpenBSD, OSX, Solaris, HP/UX, AIX
     in addition to existing support for Linux
   * Document building and installing Xymon on common platforms 
     (Linux, FreeBSD, OpenBSD, Solaris)
   * Enhance xymoncfg so it can be used to import Xymon configuration
     settings into shell-scripts.

 -- Henrik Stoerner <henrik@hswn.dk>  Sat, 4 Aug 2012 13:47:00 +0200

xymon (4.3.9) unstable; urgency=low

   * rev 7120

   * Fix crash when XYMSRV is undefined but XYMSERVERS is
   * Fix error in calculating combo-status messages with
     forward references
   * Fix error in disable-until-TIME or disable-until-OK code
   * Fix documentation of DURATION in alerts.cfg / xymond_alert so
     it is consistenly listed as being in "minutes".
   * Permit explicit use of ">" and ">=" in alerts.cfg
   * Permit building without the RRDtool libraries, e.g. for
     a network-tester build, but with trend-graphing disabled.
   * Full compiler-warning cleanup
   * Various configuration/build-script issues fixed.

 -- Henrik Stoerner <henrik@hswn.dk>  Tue, 24 Jul 2012 18:21:00 +0200

xymon (4.3.8) unstable; urgency=low

   * rev 7082

   Bugfixes
   * Workaround for DNS timeout handling, now fixed at approximately 25
     seconds.
   * "hostinfo" command for xymond documented
   * confreport only shows processes that are monitored
   * analysis.cfg parsing of COLOR for UP rules was broken
   * RRD handlers no longer crash after receiving 1 billion updates
   * Using .netrc for authentication could crash xymonnet
   * "directory" includes would report the wrong filename for missing
     directories.
   * useradm CGI would invoke htpassword twice
   * "include" and "directory" now ignores trailing whitespace
   * SSLv2 support disabled if SSL-library does not support it
   * Minor bugfixes and cleanups of compiler warnings.

   Enhancements
   * Service status on info page now links to the detailed status page.
   * Add RRDGRAPHOPTS setting to permit global user-specified RRD options,
     e.g. for font to showgraph CGI
   * Add check for the size of public keys used in SSL certificates
     (enabled via --sslkeysize=N option for xymonnet)
   * Optionally disable the display of SSL ciphers in the sslcert status
     (the --no-cipherlist option for xymonnet)
   * Improved build-scripts works on newer systems with libraries in
     new and surprising places
   * Reduce xymonnet memory usage and runtime for ping tests when there 
     are multiple hosts.cfg entries with the same IP-address.
   * Add code for inode-monitoring on Linux. Does not currently work on
     any other client platform.
   * Added the ability to disable tests until a specific time, instead of
     for some interval. Disabling a test also now computes the expire time 
     for the disable to happen at the next closest minute.

 -- Henrik Stoerner <henrik@hswn.dk>  Sun, 15 Jul 2012 17:00:00 +0200

xymon (4.3.7) unstable; urgency=low

   * rev 6803
   * Fix acknowledge CGI (broken in 4.3.6)
   * Fix broken uptime calculation for systems reporting "1 day"
   * Workaround Solaris breakage in the LFS-support detection

Changes to docs/xymon-tips.html.DIST.

22
23
24
25
26
27
28

29
30
31
32
33
34
35
...
340
341
342
343
344
345
346
347



348





































































349
350
	<li><a href="#fahrenheit">I want my temperature graphs to show Fahrenheit</a></li>
	<li><a href="#nohtmllink">How do I remove the HTML links from the alert messages?</a></li>
	<li><a href="#mancgi">I cannot see the the man-pages on the web</a></li>
	<li><a href="#mailnosubj">My alert emails come without a subject</a></li>
	<li><a href="#snmptraps">Does Xymon support receiving SNMP traps?</a></li>
	<li><a href="#scripts">How can I create a custom test script?</a></li>
	<li><a href="#ipad">How can I make the menus work on my iPad?</a></li>

</ul>
<hr>

<h3><a name="icons">What do the little red/yellow/green icons mean ?</a></h3>
<table align="center" border=1 summary="Xymon status icons">
	<tr><th align=left valign=top>Color</th><td>Recently changed</td><td>Last change &gt; 24 hours</td></tr>
	<tr><th align=left valign=top>Green: Status is OK</th><td align=center><img src="@XYMONHOSTURL@/gifs/green-recent.gif" alt="Green - recently changed"></td><td align=center><img src="@XYMONHOSTURL@/gifs/green.gif" alt="Green"></td></tr>
................................................................................
<p><tt>
In the ~xymon/server/etc/xymonmenu.cfg file, I added the 
'&lt;a href=&quot;javascript:;&quot;&gt;' anchor around the top-level menu 
items. Like:<br>
&nbsp;&nbsp;&lt;span class=&quot;menutag&quot;&gt;&lt;a href=&quot;javascript:;&quot;&gt;Views&lt;/a&gt;&lt;span class=&quot;invis&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
</tt></p>

<hr>









































































</body>
</html>







>







 








>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
	<li><a href="#fahrenheit">I want my temperature graphs to show Fahrenheit</a></li>
	<li><a href="#nohtmllink">How do I remove the HTML links from the alert messages?</a></li>
	<li><a href="#mancgi">I cannot see the the man-pages on the web</a></li>
	<li><a href="#mailnosubj">My alert emails come without a subject</a></li>
	<li><a href="#snmptraps">Does Xymon support receiving SNMP traps?</a></li>
	<li><a href="#scripts">How can I create a custom test script?</a></li>
	<li><a href="#ipad">How can I make the menus work on my iPad?</a></li>
	<li><a href="#noinstall">How can I send data to Xymon without installing the client?</a></li>
</ul>
<hr>

<h3><a name="icons">What do the little red/yellow/green icons mean ?</a></h3>
<table align="center" border=1 summary="Xymon status icons">
	<tr><th align=left valign=top>Color</th><td>Recently changed</td><td>Last change &gt; 24 hours</td></tr>
	<tr><th align=left valign=top>Green: Status is OK</th><td align=center><img src="@XYMONHOSTURL@/gifs/green-recent.gif" alt="Green - recently changed"></td><td align=center><img src="@XYMONHOSTURL@/gifs/green.gif" alt="Green"></td></tr>
................................................................................
<p><tt>
In the ~xymon/server/etc/xymonmenu.cfg file, I added the 
'&lt;a href=&quot;javascript:;&quot;&gt;' anchor around the top-level menu 
items. Like:<br>
&nbsp;&nbsp;&lt;span class=&quot;menutag&quot;&gt;&lt;a href=&quot;javascript:;&quot;&gt;Views&lt;/a&gt;&lt;span class=&quot;invis&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
</tt></p>

<hr>
<h3><a name="noinstall">How can I send data to Xymon without installing the client?</a></h3>
<p>If you cannot install any &quot;foreign&quot; tools on your system, then sending data to Xymon may be a challenge. But if you have access to either Perl, BASH or telnet on the system then it is possible.</p>
<p>Perl version:<pre><code>#!/usr/bin/perl
#
sub sendToXymon {
	use IO::Socket;
	my($server,$port,$msg) = @_ ;
	my $response;
	my $sock = new IO::Socket::INET (
			PeerAddr =&gt; $server,
			PeerPort =&gt; $port,
			Proto =&gt; 'tcp',
		);
	die &quot;Could not create socket: $!\n&quot; unless $sock;
	print $sock $msg;
	shutdown($sock, 1);
	while ($response=&lt;$sock&gt;)
	{
		print "$response";
	}
	close($sock);
}

$host = $ARGV[0];
if ($#ARGV != 2) {
  $port = 1984;
  $msg = $ARGV[1];
}
else {
  $port = $ARGV[1];
  $msg = $ARGV[2];
}

sendToXymon($host, $port, $msg);
</pre></code></p>
<p>BASH version:<pre><code>#!/bin/bash
#
HOST=&quot;$1&quot; ; shift
if test $# -gt 1; then
  PORT=&quot;$1&quot;
  shift
else
  PORT="1984"
fi
MSG=&quot;$1&quot;

exec 3&lt;&gt;/dev/tcp/$HOST/$PORT || exit 1
echo &quot;$MSG&quot; &gt;&amp;3

exit 0
</pre></code>
NOTE: The BASH support for using TCP sockets may be disabled at compile-time - some believe it is a security risk to have such an easy way of doing network I/O without requiring any special tools.</p>

<p>Bourne / Korn shell (requires telnet):<pre><code>#!/bin/sh
#
HOST=&quot;$1&quot; ; shift
if test $# -gt 1; then
  PORT=&quot;$1&quot;
  shift
else
  PORT="1984"
fi
MSG=&quot;$1&quot;

( echo "$MSG"; sleep 1 ) | telnet $HOST $PORT 2&gt;&amp;1 &gt;/dev/null | grep -v "closed by foreign host"
</pre></code></p>

<p>Both of these take 2 or 3 parameters: The Xymon host (hostname or IP-address), optionally the portnumber (1984 by default if not specified), and the message that will be sent to Xymon. The Perl version will both send data to Xymon and print out any response that is sent back - the shell-versions can only be used to send data to Xymon.</p>

<p>Oyvind Bjorge provided the core of the Perl script, and Jeremy Laidman provided the core of the shell-scripts in <a href="http://lists.xymon.com/archive/2012-August/035299.html">this thread</a> on the Xymon mailing list.</p>

<hr>

</body>
</html>

Changes to lib/links.c.

38
39
40
41
42
43
44
45
46
47

48


49
50
51
52
53
54
55
56
57
58
59
static char *hostdocurl = NULL;

char *link_docext(char *fn)
{
	char *p = strrchr(fn, '.');
	if (p == NULL) return NULL;

	if ( (strcmp(p, ".php") == 0)    ||
             (strcmp(p, ".php3") == 0)   ||
             (strcmp(p, ".asp") == 0)    ||

             (strcmp(p, ".doc") == 0)    ||


	     (strcmp(p, ".shtml") == 0)  ||
	     (strcmp(p, ".phtml") == 0)  ||
	     (strcmp(p, ".html") == 0)   ||
	     (strcmp(p, ".htm") == 0))      {
		return p;
	}

	return NULL;
}

static link_t *init_link(char *filename, char *urlprefix)







|
|
|
>
|
>
>
|
|
|
|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
static char *hostdocurl = NULL;

char *link_docext(char *fn)
{
	char *p = strrchr(fn, '.');
	if (p == NULL) return NULL;

	if ( (strcasecmp(p, ".php") == 0)    ||
             (strcasecmp(p, ".php3") == 0)   ||
             (strcasecmp(p, ".asp") == 0)    ||
             (strcasecmp(p, ".pdf") == 0)    ||
             (strcasecmp(p, ".doc") == 0)    ||
             (strcasecmp(p, ".docx") == 0)    ||
             (strcasecmp(p, ".odt") == 0)    ||
	     (strcasecmp(p, ".shtml") == 0)  ||
	     (strcasecmp(p, ".phtml") == 0)  ||
	     (strcasecmp(p, ".html") == 0)   ||
	     (strcasecmp(p, ".htm") == 0))      {
		return p;
	}

	return NULL;
}

static link_t *init_link(char *filename, char *urlprefix)

Changes to lib/loadhosts.c.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
..
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
...
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
...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
380
381
382
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
...
431
432
433
434
435
436
437

438


439
440
441
442
443
444
445
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
typedef struct pagelist_t {
	char *pagepath;
	char *pagetitle;
	struct pagelist_t *next;
} pagelist_t;

typedef struct namelist_t {
	char *ip;
	char *hostname;	/* Name for item 2 of hosts.cfg */
	char *logname;		/* Name of the host directory in XYMONHISTLOGS (underscores replaces dots). */
	int preference;		/* For host with multiple entries, mark if we have the preferred one */
	pagelist_t *page;	/* Host location in the page/subpage/subparent tree */
	void *data;		/* Misc. data supplied by the user of this library function */
	struct namelist_t *defaulthost;	/* Points to the latest ".default." host */
	int pageindex;
	char *groupid, *dgname;
	char *classname;
	char *osname;
	struct namelist_t *next;

	char *allelems;		/* Storage for data pointed to by elems */
	char **elems;		/* List of pointers to the elements of the entry */

	/* 
	 * The following are pre-parsed elements.
	 * These are pre-parsed because they are used by the xymon daemon, so
................................................................................
	 */
	char *clientname;	/* CLIENT: tag - host alias */
	char *downtime;		/* DOWNTIME tag - when host has planned downtime. */
	time_t notbefore, notafter; /* NOTBEFORE and NOTAFTER tags as time_t values */
} namelist_t;

static pagelist_t *pghead = NULL;
static namelist_t *namehead = NULL;
static namelist_t *defaulthost = NULL;
static char *xmh_item_key[XMH_LAST];
static char *xmh_item_name[XMH_LAST];
static int xmh_item_isflag[XMH_LAST];
static int configloaded = 0;
static void * rbhosts;
static void * rbclients;
................................................................................

static void initialize_hostlist(void)
{
	while (defaulthost) {
		namelist_t *walk = defaulthost;
		defaulthost = defaulthost->defaulthost;

		if (walk->ip) xfree(walk->ip);
		if (walk->hostname) xfree(walk->hostname);
		if (walk->groupid) xfree(walk->groupid);
		if (walk->dgname) xfree(walk->dgname);
		if (walk->classname) xfree(walk->classname);
		if (walk->osname) xfree(walk->osname);
		if (walk->logname) xfree(walk->logname);
		if (walk->allelems) xfree(walk->allelems);
................................................................................

	while (namehead) {
		namelist_t *walk = namehead;

		namehead = namehead->next;

		/* clientname should not be freed, since it's just a pointer into the elems-array */
		if (walk->ip) xfree(walk->ip);
		if (walk->hostname) xfree(walk->hostname);
		if (walk->groupid) xfree(walk->groupid);
		if (walk->dgname) xfree(walk->dgname);
		if (walk->classname) xfree(walk->classname);
		if (walk->osname) xfree(walk->osname);
		if (walk->logname) xfree(walk->logname);
		if (walk->allelems) xfree(walk->allelems);
		if (walk->elems) xfree(walk->elems);
		xfree(walk);
	}


	while (pghead) {
		pagelist_t *walk = pghead;

		pghead = pghead->next;
		if (walk->pagepath) xfree(walk->pagepath);
		if (walk->pagetitle) xfree(walk->pagetitle);
................................................................................
		if (walk->notafter == -1) walk->notafter = INT_MAX;
	}
}

#include "loadhosts_file.c"
#include "loadhosts_net.c"

char *knownhost(char *hostname, char **hostip, enum ghosthandling_t ghosthandling)
{
	/*
	 * ghosthandling = GH_ALLOW  : Default BB method (case-sensitive, no logging, keep ghosts)
	 * ghosthandling = GH_IGNORE : Case-insensitive, no logging, drop ghosts
	 * ghosthandling = GH_LOG    : Case-insensitive, log ghosts, drop ghosts
	 * ghosthandling = GH_MATCH  : Like GH_LOG, but try to match unknown names against known hosts
	 */
................................................................................
	xtreePos_t hosthandle;
	namelist_t *walk = NULL;
	static char *result = NULL;
	time_t now = getcurrenttime(NULL);

	if (result) xfree(result);
	result = NULL;
	if (hostip) *hostip = NULL;

	if (hivalhost) {
		*hostip = '\0';

		if (!hivalbuf || (*hivalbuf == '\0')) return NULL;

		result = (strcasecmp(hivalhost, hostname) == 0) ? strdup(hivalhost) : NULL;
		if (!result && hivals[XMH_CLIENTALIAS]) {
			result = (strcasecmp(hivals[XMH_CLIENTALIAS], hostname) == 0) ? strdup(hivalhost) : NULL;
		}

		if (result && hivals[XMH_IP] && hostip) *hostip = hivals[XMH_IP];

		return result;
	}


	/* Find the host in the normal hostname list */
	hosthandle = xtreeFind(rbhosts, hostname);
................................................................................
		}
	}

	if (walk) {
		/*
		 * Force our version of the hostname. Done here so CLIENT works always.
		 */
		*hostip = walk->ip;
		result = strdup(walk->hostname);
	}
	else {

		result = strdup(hostname);
	}

	/* If default method, just say yes */
	if (ghosthandling == GH_ALLOW) return result;

	/* Allow all summaries */
................................................................................
	namelist_t *result = NULL;
	time_t now = getcurrenttime(NULL);

	if (hivalhost) {
		return (strcasecmp(hostname, hivalhost) == 0) ? &hival_hostinfo : NULL;
	}


	if (!configloaded) load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn());



	hosthandle = xtreeFind(rbhosts, hostname);
	if (hosthandle != xtreeEnd(rbhosts)) {
		result = (namelist_t *)xtreeData(rbhosts, hosthandle);
		if ((result->notbefore > now) || (result->notafter < now)) return NULL;
	}

................................................................................
	static namelist_t *result = NULL;

	if (!result) {
		initialize_hostlist();
		result = (namelist_t *)calloc(1, sizeof(namelist_t));
	}

	result->ip = strdup("127.0.0.1");

	if (result->hostname) xfree(result->hostname);
	result->hostname = strdup(hostname);

	if (result->logname) xfree(result->logname);

	result->logname = strdup(hostname);
................................................................................
		load_hostnames(argv[1], NULL, get_fqdn());
	}

	for (argi = 2; (argi < argc); argi++) {
		char s[1024];
		char *p;
		char *hname;
		char *hostip = NULL;

handlehost:
		hname = knownhost(argv[argi], &hostip, GH_IGNORE);
		if (hname == NULL) {
			printf("Unknown host '%s'\n", argv[argi]);
			continue;
		}
		if (strcmp(hname, argv[argi])) {
			printf("Using canonical name '%s'\n", hname);
		}







|










|







 







|







 







<







 







<










>







 







|







 







<











|







 







|



>







 







>
|
>
>







 







|







 







|


|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
..
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
...
240
241
242
243
244
245
246

247
248
249
250
251
252
253
...
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
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
...
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
...
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
typedef struct pagelist_t {
	char *pagepath;
	char *pagetitle;
	struct pagelist_t *next;
} pagelist_t;

typedef struct namelist_t {
	char ip[IP_ADDR_STRLEN];
	char *hostname;	/* Name for item 2 of hosts.cfg */
	char *logname;		/* Name of the host directory in XYMONHISTLOGS (underscores replaces dots). */
	int preference;		/* For host with multiple entries, mark if we have the preferred one */
	pagelist_t *page;	/* Host location in the page/subpage/subparent tree */
	void *data;		/* Misc. data supplied by the user of this library function */
	struct namelist_t *defaulthost;	/* Points to the latest ".default." host */
	int pageindex;
	char *groupid, *dgname;
	char *classname;
	char *osname;
	struct namelist_t *next, *prev;

	char *allelems;		/* Storage for data pointed to by elems */
	char **elems;		/* List of pointers to the elements of the entry */

	/* 
	 * The following are pre-parsed elements.
	 * These are pre-parsed because they are used by the xymon daemon, so
................................................................................
	 */
	char *clientname;	/* CLIENT: tag - host alias */
	char *downtime;		/* DOWNTIME tag - when host has planned downtime. */
	time_t notbefore, notafter; /* NOTBEFORE and NOTAFTER tags as time_t values */
} namelist_t;

static pagelist_t *pghead = NULL;
static namelist_t *namehead = NULL, *nametail = NULL;
static namelist_t *defaulthost = NULL;
static char *xmh_item_key[XMH_LAST];
static char *xmh_item_name[XMH_LAST];
static int xmh_item_isflag[XMH_LAST];
static int configloaded = 0;
static void * rbhosts;
static void * rbclients;
................................................................................

static void initialize_hostlist(void)
{
	while (defaulthost) {
		namelist_t *walk = defaulthost;
		defaulthost = defaulthost->defaulthost;


		if (walk->hostname) xfree(walk->hostname);
		if (walk->groupid) xfree(walk->groupid);
		if (walk->dgname) xfree(walk->dgname);
		if (walk->classname) xfree(walk->classname);
		if (walk->osname) xfree(walk->osname);
		if (walk->logname) xfree(walk->logname);
		if (walk->allelems) xfree(walk->allelems);
................................................................................

	while (namehead) {
		namelist_t *walk = namehead;

		namehead = namehead->next;

		/* clientname should not be freed, since it's just a pointer into the elems-array */

		if (walk->hostname) xfree(walk->hostname);
		if (walk->groupid) xfree(walk->groupid);
		if (walk->dgname) xfree(walk->dgname);
		if (walk->classname) xfree(walk->classname);
		if (walk->osname) xfree(walk->osname);
		if (walk->logname) xfree(walk->logname);
		if (walk->allelems) xfree(walk->allelems);
		if (walk->elems) xfree(walk->elems);
		xfree(walk);
	}
	nametail = NULL;

	while (pghead) {
		pagelist_t *walk = pghead;

		pghead = pghead->next;
		if (walk->pagepath) xfree(walk->pagepath);
		if (walk->pagetitle) xfree(walk->pagetitle);
................................................................................
		if (walk->notafter == -1) walk->notafter = INT_MAX;
	}
}

#include "loadhosts_file.c"
#include "loadhosts_net.c"

char *knownhost(char *hostname, char *hostip, enum ghosthandling_t ghosthandling)
{
	/*
	 * ghosthandling = GH_ALLOW  : Default BB method (case-sensitive, no logging, keep ghosts)
	 * ghosthandling = GH_IGNORE : Case-insensitive, no logging, drop ghosts
	 * ghosthandling = GH_LOG    : Case-insensitive, log ghosts, drop ghosts
	 * ghosthandling = GH_MATCH  : Like GH_LOG, but try to match unknown names against known hosts
	 */
................................................................................
	xtreePos_t hosthandle;
	namelist_t *walk = NULL;
	static char *result = NULL;
	time_t now = getcurrenttime(NULL);

	if (result) xfree(result);
	result = NULL;


	if (hivalhost) {
		*hostip = '\0';

		if (!hivalbuf || (*hivalbuf == '\0')) return NULL;

		result = (strcasecmp(hivalhost, hostname) == 0) ? strdup(hivalhost) : NULL;
		if (!result && hivals[XMH_CLIENTALIAS]) {
			result = (strcasecmp(hivals[XMH_CLIENTALIAS], hostname) == 0) ? strdup(hivalhost) : NULL;
		}

		if (result && hivals[XMH_IP]) strcpy(hostip, hivals[XMH_IP]);

		return result;
	}


	/* Find the host in the normal hostname list */
	hosthandle = xtreeFind(rbhosts, hostname);
................................................................................
		}
	}

	if (walk) {
		/*
		 * Force our version of the hostname. Done here so CLIENT works always.
		 */
		strcpy(hostip, walk->ip);
		result = strdup(walk->hostname);
	}
	else {
		*hostip = '\0';
		result = strdup(hostname);
	}

	/* If default method, just say yes */
	if (ghosthandling == GH_ALLOW) return result;

	/* Allow all summaries */
................................................................................
	namelist_t *result = NULL;
	time_t now = getcurrenttime(NULL);

	if (hivalhost) {
		return (strcasecmp(hostname, hivalhost) == 0) ? &hival_hostinfo : NULL;
	}

	if (!configloaded) {
		load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn());
		configloaded = 1;
	}

	hosthandle = xtreeFind(rbhosts, hostname);
	if (hosthandle != xtreeEnd(rbhosts)) {
		result = (namelist_t *)xtreeData(rbhosts, hosthandle);
		if ((result->notbefore > now) || (result->notafter < now)) return NULL;
	}

................................................................................
	static namelist_t *result = NULL;

	if (!result) {
		initialize_hostlist();
		result = (namelist_t *)calloc(1, sizeof(namelist_t));
	}

	strcpy(result->ip, "127.0.0.1");

	if (result->hostname) xfree(result->hostname);
	result->hostname = strdup(hostname);

	if (result->logname) xfree(result->logname);

	result->logname = strdup(hostname);
................................................................................
		load_hostnames(argv[1], NULL, get_fqdn());
	}

	for (argi = 2; (argi < argc); argi++) {
		char s[1024];
		char *p;
		char *hname;
		char hostip[IP_ADDR_STRLEN];

handlehost:
		hname = knownhost(argv[argi], hostip, GH_IGNORE);
		if (hname == NULL) {
			printf("Unknown host '%s'\n", argv[argi]);
			continue;
		}
		if (strcmp(hname, argv[argi])) {
			printf("Using canonical name '%s'\n", hname);
		}

Changes to lib/loadhosts_file.c.

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
159
160
161
162
163
164
165



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
...
295
296
297
298
299
300
301
302
303
304
305
306

307









308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411

412
413
414



415

416


417
418
419
420
421
422
423

424

425
426
427
428
429
430
431
432





















433
434
435
436
437
438
439
...
440
441
442
443
444
445
446
447
448
449
450



451
452
453
454
455
456

static int prepare_fromnet(void)
{
	static char contentmd5[33] = { '\0', };
	sendreturn_t *sres;
	sendresult_t sendstat;
	char *fdata, *fhash;
	int dontsendcopy = dontsendmessages;

	dontsendmessages = 0;
	sres = newsendreturnbuf(1, NULL);
	sendstat = sendmessage("config hosts.cfg", NULL, XYMON_TIMEOUT, sres);
	dontsendmessages = dontsendcopy;
	if (sendstat != XYMONSEND_OK) {
		freesendreturnbuf(sres);
		errprintf("Cannot load hosts.cfg from xymond, code %d\n", sendstat);
		return -1;
	}

	fdata = getsendreturnstr(sres, 1);
................................................................................
	return strdup(STRBUF(contentbuffer));
}

int load_hostnames(char *hostsfn, char *extrainclude, int fqdn)
{
	/* Return value: 0 for load OK, 1 for "No files changed since last load", -1 for error (file not found) */
	int prepresult;
	int groupid, pageidx;
	char *hostname, *dgname;
	pagelist_t *curtoppage, *curpage, *pgtail;
	namelist_t *nametail = NULL;
	void * htree;
	char *cfgdata, *inbol, *ineol, insavchar = '\0';
	char *lcopy = NULL;

	load_hostinfo(NULL);

	if (*hostsfn == '!')
		prepresult = prepare_fromfile(hostsfn+1, extrainclude);
	else if (extrainclude)
		prepresult = prepare_fromfile(hostsfn, extrainclude);
................................................................................
	}

	/* Any modifications at all ? */
	if (prepresult == 1) {
		dbgprintf("No files modified, skipping reload of %s\n", hostsfn);
		return 1;
	}




	configloaded = 1;
	initialize_hostlist();
	curpage = curtoppage = pgtail = pghead;
	pageidx = groupid = 0;
	dgname = NULL;

	htree = xtreeNew(strcasecmp);
	inbol = cfgdata = hostscfg_content();
	while (inbol && *inbol) {
		char *key, *keyp;

		inbol += strspn(inbol, " \t");
		ineol = strchr(inbol, '\n'); 
		if (ineol) {
			while ((ineol > inbol) && (isspace(*ineol) || (*ineol == '\n'))) ineol--;
			if (*ineol != '\n') ineol++;

			insavchar = *ineol;
			*ineol = '\0';
		}
		if ((*inbol == '#') || (strlen(inbol) == 0)) goto nextline;

		if (lcopy) xfree(lcopy);
		lcopy = strdup(inbol);
		key = strtok_r(lcopy, " \t\r\n", &keyp);

		if (strncmp(inbol, "page", 4) == 0) {
			pagelist_t *newp;
			char *name, *title;

			pageidx = groupid = 0;
			if (dgname) xfree(dgname); dgname = NULL;
................................................................................
				pgtail->next = newp;
				pgtail = newp;

				curpage = newp;
			}
		}
		else if (strncmp(inbol, "group", 5) == 0) {
			char *tok, *inp;

			groupid++;
			if (dgname) xfree(dgname); dgname = NULL;

			tok = strtok(inbol, " \t");
			if ((strcmp(tok, "group-only") == 0) || (strcmp(tok, "group-except") == 0)) {
				tok = strtok(NULL, " \t");
................................................................................
					else {
						strcat(dgname, inp);
						inp += strlen(inp);
					}
				}
			}
		}
		else if (conn_is_ip(key) != 0) {
			char *startoftags, *tag, *delim;
			int elemidx, elemsize;
			char groupidstr[10];
			xtreePos_t handle;











			namelist_t *newitem = calloc(1, sizeof(namelist_t));
			namelist_t *iwalk, *iprev;

			hostname = strtok_r(NULL, " \t\r\n", &keyp);
			/* Hostname beginning with '@' are "no-display" hosts. But we still want them. */
			if (*hostname == '@') hostname++;

			if (!fqdn) {
				/* Strip any domain from the hostname */
				char *p = strchr(hostname, '.');
				if (p) *p = '\0';
			}

			newitem->ip = strdup(key);
			sprintf(groupidstr, "%d", groupid);
			newitem->groupid = strdup(groupidstr);
			newitem->dgname = (dgname ? strdup(dgname) : strdup("NONE"));
			newitem->pageindex = pageidx++;

			newitem->hostname = strdup(hostname);
			/* If the ip is a NULL ip, then this host has lower preference */
			newitem->preference = ((strcmp(newitem->ip, "0.0.0.0") == 0) || (strcmp(newitem->ip, "::") == 0)) ? 0 : 1;
			newitem->logname = strdup(newitem->hostname);
			{ char *p = newitem->logname; while ((p = strchr(p, '.')) != NULL) { *p = '_'; } }
			newitem->page = curpage;
			newitem->defaulthost = defaulthost;

			startoftags = strchr(inbol, '#');
			if (startoftags == NULL) startoftags = ""; else startoftags++;
................................................................................

			newitem->elems[elemidx] = NULL;

			/* See if this host is defined before */
			handle = xtreeFind(htree, newitem->hostname);
			if (strcasecmp(newitem->hostname, ".default.") == 0) {
				/* The pseudo DEFAULT host */
				newitem->next = NULL;
				defaulthost = newitem;
			}
			else if (handle == xtreeEnd(htree)) {
				/* New item, so add to end of list */
				newitem->next = NULL;
				if (namehead == NULL) 
					namehead = nametail = newitem;
				else {
					nametail->next = newitem;
					nametail = newitem;
				}
				xtreeAdd(htree, newitem->hostname, newitem);
			}
			else {
				/* Find the existing record - compare the record pointer instead of the name */
				namelist_t *existingrec = (namelist_t *)xtreeData(htree, handle);
				for (iwalk = namehead, iprev = NULL; ((iwalk != existingrec) && iwalk); iprev = iwalk, iwalk = iwalk->next) ;

 				if (newitem->preference <= iwalk->preference) {
					/* Add after the existing (more preferred) entry */
					newitem->next = iwalk->next;



					iwalk->next = newitem;

				}


				else {
					/* New item has higher preference, so add before the iwalk item (i.e. after iprev) */
					if (iprev == NULL) {
						newitem->next = namehead;
						namehead = newitem;
					}
					else {

						newitem->next = iprev->next;

						iprev->next = newitem;
					}
				}
			}

			newitem->clientname = xmh_find_item(newitem, XMH_CLIENTALIAS);
			if (newitem->clientname == NULL) newitem->clientname = newitem->hostname;
			newitem->downtime = xmh_find_item(newitem, XMH_DOWNTIME);





















		}


nextline:
		if (ineol) {
			*ineol = insavchar;
			if (*ineol != '\n') ineol = strchr(ineol, '\n');
................................................................................

			inbol = (ineol ? ineol+1 : NULL);
		}
		else
			inbol = NULL;
	}

	if (lcopy) xfree(lcopy);
	xfree(cfgdata);
	if (dgname) xfree(dgname);
	xtreeDestroy(htree);




	build_hosttree();

	return 0;
}








<

<


<







 







|
|

<


<







 







>
>
>










<
<









<
<
<
<
<







 







|







 







|




>

>
>
>
>
>
>
>
>
>
|
<

<

|







|






|
<







 







|




|









<

<
>
|

|
>
>
>
|
>
|
>
>

|
|




>
|
>
|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<



>
>
>






86
87
88
89
90
91
92

93

94
95

96
97
98
99
100
101
102
...
121
122
123
124
125
126
127
128
129
130

131
132

133
134
135
136
137
138
139
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173


174
175
176
177
178
179
180
181
182





183
184
185
186
187
188
189
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

310

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327

328
329
330
331
332
333
334
...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

407

408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
...
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482
483
484

static int prepare_fromnet(void)
{
	static char contentmd5[33] = { '\0', };
	sendreturn_t *sres;
	sendresult_t sendstat;
	char *fdata, *fhash;



	sres = newsendreturnbuf(1, NULL);
	sendstat = sendmessage("config hosts.cfg", NULL, XYMON_TIMEOUT, sres);

	if (sendstat != XYMONSEND_OK) {
		freesendreturnbuf(sres);
		errprintf("Cannot load hosts.cfg from xymond, code %d\n", sendstat);
		return -1;
	}

	fdata = getsendreturnstr(sres, 1);
................................................................................
	return strdup(STRBUF(contentbuffer));
}

int load_hostnames(char *hostsfn, char *extrainclude, int fqdn)
{
	/* Return value: 0 for load OK, 1 for "No files changed since last load", -1 for error (file not found) */
	int prepresult;
	int ip1, ip2, ip3, ip4, groupid, pageidx;
	char hostname[4096], *dgname;
	pagelist_t *curtoppage, *curpage, *pgtail;

	void * htree;
	char *cfgdata, *inbol, *ineol, insavchar = '\0';


	load_hostinfo(NULL);

	if (*hostsfn == '!')
		prepresult = prepare_fromfile(hostsfn+1, extrainclude);
	else if (extrainclude)
		prepresult = prepare_fromfile(hostsfn, extrainclude);
................................................................................
	}

	/* Any modifications at all ? */
	if (prepresult == 1) {
		dbgprintf("No files modified, skipping reload of %s\n", hostsfn);
		return 1;
	}

	MEMDEFINE(hostname);
	MEMDEFINE(l);

	configloaded = 1;
	initialize_hostlist();
	curpage = curtoppage = pgtail = pghead;
	pageidx = groupid = 0;
	dgname = NULL;

	htree = xtreeNew(strcasecmp);
	inbol = cfgdata = hostscfg_content();
	while (inbol && *inbol) {


		inbol += strspn(inbol, " \t");
		ineol = strchr(inbol, '\n'); 
		if (ineol) {
			while ((ineol > inbol) && (isspace(*ineol) || (*ineol == '\n'))) ineol--;
			if (*ineol != '\n') ineol++;

			insavchar = *ineol;
			*ineol = '\0';
		}






		if (strncmp(inbol, "page", 4) == 0) {
			pagelist_t *newp;
			char *name, *title;

			pageidx = groupid = 0;
			if (dgname) xfree(dgname); dgname = NULL;
................................................................................
				pgtail->next = newp;
				pgtail = newp;

				curpage = newp;
			}
		}
		else if (strncmp(inbol, "group", 5) == 0) {
			char *tok;

			groupid++;
			if (dgname) xfree(dgname); dgname = NULL;

			tok = strtok(inbol, " \t");
			if ((strcmp(tok, "group-only") == 0) || (strcmp(tok, "group-except") == 0)) {
				tok = strtok(NULL, " \t");
................................................................................
					else {
						strcat(dgname, inp);
						inp += strlen(inp);
					}
				}
			}
		}
		else if (sscanf(inbol, "%d.%d.%d.%d %s", &ip1, &ip2, &ip3, &ip4, hostname) == 5) {
			char *startoftags, *tag, *delim;
			int elemidx, elemsize;
			char groupidstr[10];
			xtreePos_t handle;
			namelist_t *newitem;

			if ( (ip1 < 0) || (ip1 > 255) ||
			     (ip2 < 0) || (ip2 > 255) ||
			     (ip3 < 0) || (ip3 > 255) ||
			     (ip4 < 0) || (ip4 > 255)) {
				errprintf("Invalid IPv4-address for host %s (nibble outside 0-255 range): %d.%d.%d.%d\n",
					  hostname, ip1, ip2, ip3, ip4);
				goto nextline;
			}

			newitem = calloc(1, sizeof(namelist_t));



			/* Hostname beginning with '@' are "no-display" hosts. But we still want them. */
			if (*hostname == '@') memmove(hostname, hostname+1, strlen(hostname));

			if (!fqdn) {
				/* Strip any domain from the hostname */
				char *p = strchr(hostname, '.');
				if (p) *p = '\0';
			}

			sprintf(newitem->ip, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
			sprintf(groupidstr, "%d", groupid);
			newitem->groupid = strdup(groupidstr);
			newitem->dgname = (dgname ? strdup(dgname) : strdup("NONE"));
			newitem->pageindex = pageidx++;

			newitem->hostname = strdup(hostname);
			if (ip1 || ip2 || ip3 || ip4) newitem->preference = 1; else newitem->preference = 0;

			newitem->logname = strdup(newitem->hostname);
			{ char *p = newitem->logname; while ((p = strchr(p, '.')) != NULL) { *p = '_'; } }
			newitem->page = curpage;
			newitem->defaulthost = defaulthost;

			startoftags = strchr(inbol, '#');
			if (startoftags == NULL) startoftags = ""; else startoftags++;
................................................................................

			newitem->elems[elemidx] = NULL;

			/* See if this host is defined before */
			handle = xtreeFind(htree, newitem->hostname);
			if (strcasecmp(newitem->hostname, ".default.") == 0) {
				/* The pseudo DEFAULT host */
				newitem->next = newitem->prev = NULL;
				defaulthost = newitem;
			}
			else if (handle == xtreeEnd(htree)) {
				/* New item, so add to end of list */
				newitem->prev = nametail; newitem->next = NULL;
				if (namehead == NULL) 
					namehead = nametail = newitem;
				else {
					nametail->next = newitem;
					nametail = newitem;
				}
				xtreeAdd(htree, newitem->hostname, newitem);
			}
			else {

				namelist_t *existingrec = (namelist_t *)xtreeData(htree, handle);


 				if (newitem->preference <= existingrec->preference) {
					/* Add after the existing (more preferred) entry */
					newitem->next = existingrec->next;
					/* NB: existingrec may be the end of the list, so existingrec->next can be NULL */
					if (newitem->next) newitem->next->prev = newitem;

					existingrec->next = newitem;
					newitem->prev = existingrec;

					if (newitem->next == NULL) nametail = newitem;
				}
				else {
					/* New item has higher preference, so add before the current item (i.e. after existingrec->prev) */
					if (existingrec->prev == NULL) {
						newitem->next = namehead;
						namehead = newitem;
					}
					else {
						newitem->prev = existingrec->prev;
						newitem->next = existingrec;
						existingrec->prev = newitem;
						newitem->prev->next = newitem;
					}
				}
			}

			newitem->clientname = xmh_find_item(newitem, XMH_CLIENTALIAS);
			if (newitem->clientname == NULL) newitem->clientname = newitem->hostname;
			newitem->downtime = xmh_find_item(newitem, XMH_DOWNTIME);

#ifdef DEBUG
			{
				namelist_t *walk;
				int err = 0;

				for (walk = namehead; (walk && !err); walk = walk->next) {
					// printf("%s	%s	%s\n", walk->hostname, (walk->next ? walk->next->hostname: "<null>"), (walk->prev ? walk->prev->hostname : "<null>"));
					if (walk->next && (walk->next->prev != walk)) 
						{ printf("*** ERROR: next->prev is not self\n"); err = 1; }
					if (!walk->next && (walk != nametail)) 
						{ printf("*** ERROR: No next element, but nametail is different\n"); err = 1; }
					if (!walk->prev && (walk != namehead)) 
						{ printf("*** ERROR: No prev element, but namehead is different\n"); err = 1; }
				}

				if (err)
					printf("Error\n");
			}
#endif

		}


nextline:
		if (ineol) {
			*ineol = insavchar;
			if (*ineol != '\n') ineol = strchr(ineol, '\n');
................................................................................

			inbol = (ineol ? ineol+1 : NULL);
		}
		else
			inbol = NULL;
	}


	xfree(cfgdata);
	if (dgname) xfree(dgname);
	xtreeDestroy(htree);

	MEMUNDEFINE(hostname);
	MEMUNDEFINE(l);

	build_hosttree();

	return 0;
}

Changes to lib/strfunc.c.

183
184
185
186
187
188
189


190
191
192
193
194
195
196
	/*
	 * This routine converts a plain string into an html-quoted string
	 */

	static strbuffer_t *result = NULL;
	char *inp, *endp;
	char c;



	if (!result) result = newstrbuffer(4096);
	clearstrbuffer(result);

	inp = s;
	do {
		endp = inp + strcspn(inp, "\"&<> ");







>
>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
	/*
	 * This routine converts a plain string into an html-quoted string
	 */

	static strbuffer_t *result = NULL;
	char *inp, *endp;
	char c;

	if (!s) return NULL;

	if (!result) result = newstrbuffer(4096);
	clearstrbuffer(result);

	inp = s;
	do {
		endp = inp + strcspn(inp, "\"&<> ");

Changes to lib/tree.c.

32
33
34
35
36
37
38


39
40
41
42
43
44
45
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
	xtreePos_t treesz;
	int (*compare)(const char *a, const char *b);
} xtree_t;

static xtreePos_t binsearch(xtree_t *mytree, char *key)
{
	xtreePos_t uplim, lowlim, n;



	/* Do a binary search  */
	lowlim = 0; uplim = mytree->treesz-1;

	do {
		xtreePos_t res;

................................................................................
	xtree_t *mytree = (xtree_t *)treehandle;

	/* Does tree exist ? Is it empty? */
	if ((treehandle == NULL) || (mytree->treesz == 0) || (pos >= (mytree->treesz - 1)) || (pos < 0)) return -1;

	do {
		pos++;
	} while ((pos < mytree->treesz) && (mytree->entries[pos].deleted != 0));

	return pos;
}

char *xtreeKey(void *treehandle, xtreePos_t pos)
{
	xtree_t *mytree = (xtree_t *)treehandle;

	/* Does tree exist ? Is it empty? */
................................................................................
	else {
		n = binsearch(mytree, key);

		if ((n >= 0) && (n < mytree->treesz) && (mytree->compare(key, mytree->entries[n].key) == 0)) {
			/* Record already exists */

			if (mytree->entries[n].deleted != 0) {
				/* Revive the old record. Note that we can now discard are privately held key */
				free(mytree->entries[n].key);

				mytree->entries[n].key = key;
				mytree->entries[n].deleted = 0;
				mytree->entries[n].userdata = userdata;
				return XTREE_STATUS_OK;
			}







>
>







 







|

|







 







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
	xtreePos_t treesz;
	int (*compare)(const char *a, const char *b);
} xtree_t;

static xtreePos_t binsearch(xtree_t *mytree, char *key)
{
	xtreePos_t uplim, lowlim, n;

	if (!key) return -1;

	/* Do a binary search  */
	lowlim = 0; uplim = mytree->treesz-1;

	do {
		xtreePos_t res;

................................................................................
	xtree_t *mytree = (xtree_t *)treehandle;

	/* Does tree exist ? Is it empty? */
	if ((treehandle == NULL) || (mytree->treesz == 0) || (pos >= (mytree->treesz - 1)) || (pos < 0)) return -1;

	do {
		pos++;
	} while (mytree->entries[pos].deleted && (pos < mytree->treesz));

	return (pos < mytree->treesz) ? pos : -1;
}

char *xtreeKey(void *treehandle, xtreePos_t pos)
{
	xtree_t *mytree = (xtree_t *)treehandle;

	/* Does tree exist ? Is it empty? */
................................................................................
	else {
		n = binsearch(mytree, key);

		if ((n >= 0) && (n < mytree->treesz) && (mytree->compare(key, mytree->entries[n].key) == 0)) {
			/* Record already exists */

			if (mytree->entries[n].deleted != 0) {
				/* Revive the old record. Note that we can now discard our privately held key */
				free(mytree->entries[n].key);

				mytree->entries[n].key = key;
				mytree->entries[n].deleted = 0;
				mytree->entries[n].userdata = userdata;
				return XTREE_STATUS_OK;
			}

Changes to xymond/do_alert.c.

408
409
410
411
412
413
414






415
416
417
418
419
420
421
422
423
424
425
426
427
428
...
503
504
505
506
507
508
509

510
511
512
513
514
515
516
517
...
542
543
544
545
546
547
548









549
550
551
552
553
554
555
556
557
			/*
			 * This runs in a child-process context, so the record we
			 * might create here is NOT used later on.
			 */
			rpt = find_repeatinfo(alert, recip, 1);
			if (!rpt) continue;	/* Happens for e.g. M_IGNORE recipients */







			dbgprintf("  repeat %s at %d\n", rpt->recipid, rpt->nextalert);
			if (rpt->nextalert > now) {
				traceprintf("Recipient '%s' dropped, next alert due at %ld > %ld\n",
						rpt->recipid, (long)rpt->nextalert, (long)now);
				continue;
			}
			alertcount++;
		}
		else if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
			/* RECOVERED messages require that we've sent out an alert before */
			repeat_t *rpt = NULL;

			rpt = find_repeatinfo(alert, recip, 0);
			if (!rpt) continue;
................................................................................

				scriptrecip = message_recipient(recip->recipient, alert->hostname, alert->testname, colorname(alert->color));
				scriptpid = fork();
				if (scriptpid == 0) {
					/* Setup all of the environment for a paging script */
					void *hinfo;
					char *p;

					char *bbalphamsg, *ackcode, *rcpt, *bbhostname, *bbhostsvc, *bbhostsvccommas, *machip, *bbsvcname, *bbsvcnum, *bbcolorlevel, *recovered, *downsecs, *eventtstamp, *downsecsmsg, *cfidtxt;
					char *alertid, *alertidenv;
					int msglen;

					cfidtxt = (char *)malloc(strlen("CFID=") + 10);
					sprintf(cfidtxt, "CFID=%d", recip->cfid);
					putenv(cfidtxt);

................................................................................
					sprintf(bbhostsvc, "BBHOSTSVC=%s.%s", alert->hostname, alert->testname);
					putenv(bbhostsvc);

					bbhostsvccommas = (char *)malloc(strlen("BBHOSTSVCCOMMAS=") + strlen(alert->hostname) + 1 + strlen(alert->testname) + 1);
					sprintf(bbhostsvccommas, "BBHOSTSVCCOMMAS=%s.%s", commafy(alert->hostname), alert->testname);
					putenv(bbhostsvccommas);










					machip = (char *)malloc(strlen("MACHIP=") + strlen(alert->ip) + 1);
					sprintf(machip, "MACHIP=%s", alert->ip);
					putenv(machip);

					bbsvcname = (char *)malloc(strlen("BBSVCNAME=") + strlen(alert->testname) + 1);
					sprintf(bbsvcname, "BBSVCNAME=%s", alert->testname);
					putenv(bbsvcname);

					bbsvcnum = (char *)malloc(strlen("BBSVCNUM=") + 10);







>
>
>
>
>
>






<







 







>
|







 







>
>
>
>
>
>
>
>
>
|
|







408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
...
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
			/*
			 * This runs in a child-process context, so the record we
			 * might create here is NOT used later on.
			 */
			rpt = find_repeatinfo(alert, recip, 1);
			if (!rpt) continue;	/* Happens for e.g. M_IGNORE recipients */

			/* 
			 * Update alertcount here, because we dont want to hit an UNMATCHED
			 * rule when there is actually an alert active - it is just suppressed
			 * for this run due to the REPEAT setting.
			 */
			alertcount++;	
			dbgprintf("  repeat %s at %d\n", rpt->recipid, rpt->nextalert);
			if (rpt->nextalert > now) {
				traceprintf("Recipient '%s' dropped, next alert due at %ld > %ld\n",
						rpt->recipid, (long)rpt->nextalert, (long)now);
				continue;
			}

		}
		else if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
			/* RECOVERED messages require that we've sent out an alert before */
			repeat_t *rpt = NULL;

			rpt = find_repeatinfo(alert, recip, 0);
			if (!rpt) continue;
................................................................................

				scriptrecip = message_recipient(recip->recipient, alert->hostname, alert->testname, colorname(alert->color));
				scriptpid = fork();
				if (scriptpid == 0) {
					/* Setup all of the environment for a paging script */
					void *hinfo;
					char *p;
					int ip1=0, ip2=0, ip3=0, ip4=0;
					char *bbalphamsg, *ackcode, *rcpt, *bbhostname, *bbhostsvc, *bbhostsvccommas, *bbnumeric, *machip, *bbsvcname, *bbsvcnum, *bbcolorlevel, *recovered, *downsecs, *eventtstamp, *downsecsmsg, *cfidtxt;
					char *alertid, *alertidenv;
					int msglen;

					cfidtxt = (char *)malloc(strlen("CFID=") + 10);
					sprintf(cfidtxt, "CFID=%d", recip->cfid);
					putenv(cfidtxt);

................................................................................
					sprintf(bbhostsvc, "BBHOSTSVC=%s.%s", alert->hostname, alert->testname);
					putenv(bbhostsvc);

					bbhostsvccommas = (char *)malloc(strlen("BBHOSTSVCCOMMAS=") + strlen(alert->hostname) + 1 + strlen(alert->testname) + 1);
					sprintf(bbhostsvccommas, "BBHOSTSVCCOMMAS=%s.%s", commafy(alert->hostname), alert->testname);
					putenv(bbhostsvccommas);

					bbnumeric = (char *)malloc(strlen("BBNUMERIC=") + 22 + 1);
					p = bbnumeric;
					p += sprintf(p, "BBNUMERIC=");
					p += sprintf(p, "%03d", servicecode(alert->testname));
					sscanf(alert->ip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
					p += sprintf(p, "%03d%03d%03d%03d", ip1, ip2, ip3, ip4);
					p += sprintf(p, "%d", alert->cookie);
					putenv(bbnumeric);

					machip = (char *)malloc(strlen("MACHIP=") + 13);
					sprintf(machip, "MACHIP=%03d%03d%03d%03d", ip1, ip2, ip3, ip4);
					putenv(machip);

					bbsvcname = (char *)malloc(strlen("BBSVCNAME=") + strlen(alert->testname) + 1);
					sprintf(bbsvcname, "BBSVCNAME=%s", alert->testname);
					putenv(bbsvcname);

					bbsvcnum = (char *)malloc(strlen("BBSVCNUM=") + 10);

Changes to xymond/webfiles/trends_form.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    <TR><TD BGCOLOR="#333333" ALIGN="CENTER">Trends period</TD></TR>
    <TR>
       <TD BGCOLOR="#333333">
       <BR>
       <CENTER>

       <FORM METHOD="GET" ACTION="&SCRIPT_NAME">
          <INPUT TYPE="HIDDEN" NAME="HOST" VALUE="&XYMWEBHOST">
          <INPUT TYPE="HIDDEN" NAME="SERVICE" VALUE="&XYMWEBSVC">

       <TABLE>
         <TR>
	    <TD COLSPAN=3>
	       <table border=0>
	         <tr>







|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    <TR><TD BGCOLOR="#333333" ALIGN="CENTER">Trends period</TD></TR>
    <TR>
       <TD BGCOLOR="#333333">
       <BR>
       <CENTER>

       <FORM METHOD="GET" ACTION="&SCRIPT_NAME">
          <INPUT TYPE="HIDDEN" NAME="HOST" VALUE="&XMH_HOSTNAME">
          <INPUT TYPE="HIDDEN" NAME="SERVICE" VALUE="&XYMWEBSVC">

       <TABLE>
         <TR>
	    <TD COLSPAN=3>
	       <table border=0>
	         <tr>

Changes to xymond/xymond_channel.c.

73
74
75
76
77
78
79
80



81

82
83
84
85
86
87
88
...
221
222
223
224
225
226
227


228
229
230
231
232
233
234
...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424


425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441



442
443
444
445
446
447
448
449
450
451
452
















453
454
455
456
457
458
459
...
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
...
561
562
563
564
565
566
567










568
569
570
571
572
573
574
...
775
776
777
778
779
780
781
782
783
784
785
786
	/* For P_LOCAL peers */
	char *childcmd;				/* Command and arguments for the child process */
	char **childargs;
	pid_t childpid;				/* PID of the running worker child */
} xymon_peer_t;

void * peers;




xymond_channel_t *channel = NULL;

int locatorbased = 0;
enum locator_servicetype_t locatorservice = ST_MAX;

static int running = 1;
static int gotalarm = 0;
static int pendingcount = 0;

................................................................................
		else if (childpid == 0) {
			/* The channel handler child */
			if (logfn) {
				char *logfnenv = (char *)malloc(strlen(logfn) + 30);
				sprintf(logfnenv, "XYMONCHANNEL_LOGFILENAME=%s", logfn);
				putenv(logfnenv);
			}



			n = dup2(pfd[0], STDIN_FILENO);
			close(pfd[0]); close(pfd[1]);
			n = execvp(peer->childcmd, peer->childargs);
			
			/* We should never go here */
			errprintf("exec() failed for child command %s: %s\n", 
................................................................................
	while (peer->msghead) flushmessage(peer);
	peer->msghead = peer->msgtail = NULL;
}


void sig_handler(int signum)
{
	int childexit;

	switch (signum) {
	  case SIGTERM:
	  case SIGINT:
		/* Shutting down. */
		running = 0;
		break;

	  case SIGCHLD:
		/* Our worker child died. Avoid zombies. */
		wait(&childexit);
		break;

	  case SIGALRM:
		gotalarm = 1;
		break;
	}
}


int main(int argc, char *argv[])
{
	int daemonize = 0;


	int cnid = -1;
	pcre *msgfilter = NULL;
	pcre *stdfilter = NULL;

	int argi;
	struct sigaction sa;
	xtreePos_t handle;

	libxymon_init(argv[0]);

	/* Dont save the error buffer */
	save_errbuf = 0;

	/* Create the peer container */
	peers = xtreeNew(strcasecmp);

	for (argi=1; (argi < argc); argi++) {



		if (argnmatch(argv[argi], "--channel=")) {
			char *cn = strchr(argv[argi], '=') + 1;

			for (cnid = C_STATUS; (channelnames[cnid] && strcmp(channelnames[cnid], cn)); cnid++) ;
			if (channelnames[cnid] == NULL) cnid = -1;
		}
		else if (argnmatch(argv[argi], "--daemon")) {
			daemonize = 1;
		}
		else if (argnmatch(argv[argi], "--no-daemon")) {
			daemonize = 0;
















		}
		else if (argnmatch(argv[argi], "--locator=")) {
			char *p = strchr(argv[argi], '=');
			locator_init(p+1);
			locatorbased = 1;
		}
		else if (argnmatch(argv[argi], "--service=")) {
................................................................................
		}
		else if (argnmatch(argv[argi], "--md5")) {
			checksumsize = 33;
		}
		else if (argnmatch(argv[argi], "--no-md5")) {
			checksumsize = 0;
		}
		else if (standardoption(argv[argi])) {
			if (showhelp) return 0;
		}
		else {
			char *childcmd;
			char **childargs;
			int i = 0;

			childcmd = argv[argi];
			childargs = (char **) calloc((1 + argc - argi), sizeof(char *));
................................................................................
			/* Fork failed */
			errprintf("Could not fork child\n");
			exit(1);
		}
		else if (daemonpid > 0) {
			/* Parent creates PID file and exits */
			FILE *fd = NULL;
			if (pidfn) fd = fopen(pidfn, "w");
			if (fd) {
				fprintf(fd, "%d\n", (int)daemonpid);
				fclose(fd);
			}
			exit(0);
		}
		/* Child (daemon) continues here */
................................................................................
		 * Note that we use IPC_NOWAIT if there are messages in the
		 * queue, because then we just want to pick up a message if
		 * there is one, and if not we want to continue pushing the
		 * queued data to the worker.
		 */
		struct sembuf s;
		int n;











		s.sem_num = GOCLIENT; s.sem_op  = -1; s.sem_flg = ((pendingcount > 0) ? IPC_NOWAIT : 0);
		n = semop(channel->semid, &s, 1);

		if (n == 0) {
			/*
			 * GOCLIENT went high, and so we got alerted about a new
................................................................................
	/* Close peer connections */
	for (handle = xtreeFirst(peers); (handle != xtreeEnd(peers)); handle = xtreeNext(peers, handle)) {
		xymon_peer_t *pwalk = (xymon_peer_t *) xtreeData(peers, handle);
		shutdownconnection(pwalk);
	}

	/* Remove the PID file */
	if (pidfn) unlink(pidfn);

	return 0;
}









>
>
>

>







 







>
>







 







<
<









|












>
>








<








>
>
>
|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<







 







|







 







>
>
>
>
>
>
>
>
>
>







 







|




73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
400
401
402
403
404
405
406


407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
...
496
497
498
499
500
501
502



503
504
505
506
507
508
509
...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
...
806
807
808
809
810
811
812
813
814
815
816
817
	/* For P_LOCAL peers */
	char *childcmd;				/* Command and arguments for the child process */
	char **childargs;
	pid_t childpid;				/* PID of the running worker child */
} xymon_peer_t;

void * peers;

pid_t deadpid = 0;
int childexit;

xymond_channel_t *channel = NULL;
char *logfn = NULL;
int locatorbased = 0;
enum locator_servicetype_t locatorservice = ST_MAX;

static int running = 1;
static int gotalarm = 0;
static int pendingcount = 0;

................................................................................
		else if (childpid == 0) {
			/* The channel handler child */
			if (logfn) {
				char *logfnenv = (char *)malloc(strlen(logfn) + 30);
				sprintf(logfnenv, "XYMONCHANNEL_LOGFILENAME=%s", logfn);
				putenv(logfnenv);
			}

			dbgprintf("Child '%s' started (PID %d), about to fork\n", peer->childcmd, (int)getpid());

			n = dup2(pfd[0], STDIN_FILENO);
			close(pfd[0]); close(pfd[1]);
			n = execvp(peer->childcmd, peer->childargs);
			
			/* We should never go here */
			errprintf("exec() failed for child command %s: %s\n", 
................................................................................
	while (peer->msghead) flushmessage(peer);
	peer->msghead = peer->msgtail = NULL;
}


void sig_handler(int signum)
{


	switch (signum) {
	  case SIGTERM:
	  case SIGINT:
		/* Shutting down. */
		running = 0;
		break;

	  case SIGCHLD:
		/* Our worker child died. Avoid zombies. */
		deadpid = wait(&childexit);
		break;

	  case SIGALRM:
		gotalarm = 1;
		break;
	}
}


int main(int argc, char *argv[])
{
	int daemonize = 0;
	char *pidfile = NULL;
	char *envarea = NULL;
	int cnid = -1;
	pcre *msgfilter = NULL;
	pcre *stdfilter = NULL;

	int argi;
	struct sigaction sa;
	xtreePos_t handle;



	/* Dont save the error buffer */
	save_errbuf = 0;

	/* Create the peer container */
	peers = xtreeNew(strcasecmp);

	for (argi=1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--debug")) {
			debug = 1;
		}
		else if (argnmatch(argv[argi], "--channel=")) {
			char *cn = strchr(argv[argi], '=') + 1;

			for (cnid = C_STATUS; (channelnames[cnid] && strcmp(channelnames[cnid], cn)); cnid++) ;
			if (channelnames[cnid] == NULL) cnid = -1;
		}
		else if (argnmatch(argv[argi], "--daemon")) {
			daemonize = 1;
		}
		else if (argnmatch(argv[argi], "--no-daemon")) {
			daemonize = 0;
		}
		else if (argnmatch(argv[argi], "--pidfile=")) {
			char *p = strchr(argv[argi], '=');
			pidfile = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--log=")) {
			char *p = strchr(argv[argi], '=');
			logfn = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--env=")) {
			char *p = strchr(argv[argi], '=');
			loadenv(p+1, envarea);
		}
		else if (argnmatch(argv[argi], "--area=")) {
			char *p = strchr(argv[argi], '=');
			envarea = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--locator=")) {
			char *p = strchr(argv[argi], '=');
			locator_init(p+1);
			locatorbased = 1;
		}
		else if (argnmatch(argv[argi], "--service=")) {
................................................................................
		}
		else if (argnmatch(argv[argi], "--md5")) {
			checksumsize = 33;
		}
		else if (argnmatch(argv[argi], "--no-md5")) {
			checksumsize = 0;
		}



		else {
			char *childcmd;
			char **childargs;
			int i = 0;

			childcmd = argv[argi];
			childargs = (char **) calloc((1 + argc - argi), sizeof(char *));
................................................................................
			/* Fork failed */
			errprintf("Could not fork child\n");
			exit(1);
		}
		else if (daemonpid > 0) {
			/* Parent creates PID file and exits */
			FILE *fd = NULL;
			if (pidfile) fd = fopen(pidfile, "w");
			if (fd) {
				fprintf(fd, "%d\n", (int)daemonpid);
				fclose(fd);
			}
			exit(0);
		}
		/* Child (daemon) continues here */
................................................................................
		 * Note that we use IPC_NOWAIT if there are messages in the
		 * queue, because then we just want to pick up a message if
		 * there is one, and if not we want to continue pushing the
		 * queued data to the worker.
		 */
		struct sembuf s;
		int n;

		if (deadpid != 0) {
			char *cause = "Unknown";
			int ecode = -1;

			if (WIFEXITED(childexit)) { cause = "Exit status"; ecode = WEXITSTATUS(childexit); }
			else if (WIFSIGNALED(childexit)) { cause = "Signal"; ecode = WTERMSIG(childexit); }
			errprintf("Child process %d died: %s %d\n", deadpid, cause, ecode);
			deadpid = 0;
		}

		s.sem_num = GOCLIENT; s.sem_op  = -1; s.sem_flg = ((pendingcount > 0) ? IPC_NOWAIT : 0);
		n = semop(channel->semid, &s, 1);

		if (n == 0) {
			/*
			 * GOCLIENT went high, and so we got alerted about a new
................................................................................
	/* Close peer connections */
	for (handle = xtreeFirst(peers); (handle != xtreeEnd(peers)); handle = xtreeNext(peers, handle)) {
		xymon_peer_t *pwalk = (xymon_peer_t *) xtreeData(peers, handle);
		shutdownconnection(pwalk);
	}

	/* Remove the PID file */
	if (pidfile) unlink(pidfile);

	return 0;
}

Changes to xymond/xymond_rrd.c.

185
186
187
188
189
190
191
192
193
194
195



196
197
198
199
200
201
202
203
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
	struct sigaction sa;
	char *exthandler = NULL;
	char *extids = NULL;
	char *processor = NULL;
	struct sockaddr_un ctlsockaddr;
	int ctlsocket;

	libxymon_init(argv[0]);

	/* Handle program options. */
	for (argi = 1; (argi < argc); argi++) {



		if (argnmatch(argv[argi], "--rrddir=")) {
			char *p = strchr(argv[argi], '=');
			rrddir = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--extra-script=")) {
			char *p = strchr(argv[argi], '=');
			exthandler = strdup(p+1);
		}
................................................................................
		}
		else if (strcmp(argv[argi], "--no-cache") == 0) {
			use_rrd_cache = 0;
		}
		else if (net_worker_option(argv[argi])) {
			/* Handled in the subroutine */
		}
		else if (standardoption(argv[argi])) {
			if (showhelp) return 0;
		}
	}

	save_errbuf = 0;

	if ((rrddir == NULL) && xgetenv("XYMONRRDS")) {
		rrddir = strdup(xgetenv("XYMONRRDS"));
	}
................................................................................
		p = gettok(msg, "|");
		while (p && (metacount < MAX_META)) {
			metadata[metacount++] = p;
			p = gettok(NULL, "|");
		}
		metadata[metacount] = NULL;

		if ((metacount >= 14) && (strncmp(metadata[0], "@@status", 8) == 0)) {
			/*
			 * @@status|timestamp|sender|origin|hostname|testname|expiretime|color|testflags|\
			 * prevcolor|changetime|ackexpiretime|ackmessage|disableexpiretime|disablemessage|\
			 * clienttstamp|flapping|classname|pagepaths
			 */
			int color = parse_color(metadata[7]);

................................................................................
				break;

			  default:
				/* Ignore reports with purple, blue or clear - they have no data we want. */
				break;
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@data", 6) == 0)) {
			/* @@data|timestamp|sender|origin|hostname|testname|classname|pagepaths */
			tstamp = atoi(metadata[1]);
			sender = metadata[2];
			hostname = metadata[4]; 
			testname = metadata[5];
			classname = (metadata[6] ? metadata[6] : "");
			pagepaths = (metadata[7] ? metadata[7] : "");







<
<


>
>
>
|







 







<
<
<







 







|







 







|







185
186
187
188
189
190
191


192
193
194
195
196
197
198
199
200
201
202
203
204
...
212
213
214
215
216
217
218



219
220
221
222
223
224
225
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
	struct sigaction sa;
	char *exthandler = NULL;
	char *extids = NULL;
	char *processor = NULL;
	struct sockaddr_un ctlsockaddr;
	int ctlsocket;



	/* Handle program options. */
	for (argi = 1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}
		else if (argnmatch(argv[argi], "--rrddir=")) {
			char *p = strchr(argv[argi], '=');
			rrddir = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--extra-script=")) {
			char *p = strchr(argv[argi], '=');
			exthandler = strdup(p+1);
		}
................................................................................
		}
		else if (strcmp(argv[argi], "--no-cache") == 0) {
			use_rrd_cache = 0;
		}
		else if (net_worker_option(argv[argi])) {
			/* Handled in the subroutine */
		}



	}

	save_errbuf = 0;

	if ((rrddir == NULL) && xgetenv("XYMONRRDS")) {
		rrddir = strdup(xgetenv("XYMONRRDS"));
	}
................................................................................
		p = gettok(msg, "|");
		while (p && (metacount < MAX_META)) {
			metadata[metacount++] = p;
			p = gettok(NULL, "|");
		}
		metadata[metacount] = NULL;

		if ((metacount >= 14) && (strncmp(metadata[0], "@@status", 8) == 0) && restofmsg) {
			/*
			 * @@status|timestamp|sender|origin|hostname|testname|expiretime|color|testflags|\
			 * prevcolor|changetime|ackexpiretime|ackmessage|disableexpiretime|disablemessage|\
			 * clienttstamp|flapping|classname|pagepaths
			 */
			int color = parse_color(metadata[7]);

................................................................................
				break;

			  default:
				/* Ignore reports with purple, blue or clear - they have no data we want. */
				break;
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@data", 6) == 0) && restofmsg) {
			/* @@data|timestamp|sender|origin|hostname|testname|classname|pagepaths */
			tstamp = atoi(metadata[1]);
			sender = metadata[2];
			hostname = metadata[4]; 
			testname = metadata[5];
			classname = (metadata[6] ? metadata[6] : "");
			pagepaths = (metadata[7] ? metadata[7] : "");

Changes to xymongen/loaddata.c.

482
483
484
485
486
487
488

489
490
491
492
493
494
495
...
501
502
503
504
505
506
507

508


509

510
511
512
513
514
515
516

	dbgprintf("load_state()\n");

	sres = newsendreturnbuf(1, NULL);

	if (!reportstart && !snapshot) {
		char *dumpfn = getenv("BOARDDUMP");


		if (dumpfn) {
			/* Debugging - read data from a dump file */
			struct stat st;
			FILE *fd;

			xymondresult = XYMONSEND_ETIMEOUT;
................................................................................
						fclose(fd);
						xymondresult = XYMONSEND_OK;
					}
				}
			}
		}
		else {

			xymondresult = sendmessage("xymondboard fields=hostname,testname,color,flags,lastchange,logtime,validtime,acktime,disabletime,sender,cookie,line1,acklist", NULL, XYMON_TIMEOUT, sres);


			board = getsendreturnstr(sres, 1);

		}
	}
	else {
		xymondresult = sendmessage("xymondboard fields=hostname,testname", NULL, XYMON_TIMEOUT, sres);
		board = getsendreturnstr(sres, 1);
	}








>







 







>
|
>
>

>







482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521

	dbgprintf("load_state()\n");

	sres = newsendreturnbuf(1, NULL);

	if (!reportstart && !snapshot) {
		char *dumpfn = getenv("BOARDDUMP");
		char *filter = getenv("BOARDFILTER");

		if (dumpfn) {
			/* Debugging - read data from a dump file */
			struct stat st;
			FILE *fd;

			xymondresult = XYMONSEND_ETIMEOUT;
................................................................................
						fclose(fd);
						xymondresult = XYMONSEND_OK;
					}
				}
			}
		}
		else {
			char *bcmd = (char *)malloc(1024 + (filter ? strlen(filter) : 0);
			sprintf(bcmd, "xymondboard %s %s", "fields=hostname,testname,color,flags,lastchange,logtime,validtime,acktime,disabletime,sender,cookie,line1,acklist", (filter ? filter : ""));

			xymondresult = sendmessage(bcmd, NULL, XYMON_TIMEOUT, sres);
			board = getsendreturnstr(sres, 1);
			xfree(bcmd);
		}
	}
	else {
		xymondresult = sendmessage("xymondboard fields=hostname,testname", NULL, XYMON_TIMEOUT, sres);
		board = getsendreturnstr(sres, 1);
	}

Changes to xymongen/pagegen.c.

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
...
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
....
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
....
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
	 * I.e. it generates buttons and links to all the hosts for
	 * a test, and the host docs.
	 */

	host_t	*h;
	entry_t	*e;
	char	*xymonskin;
	int	rowcount = 0, hostcount = 0;
	int	width;
	int	hidx;
	void	*vptree;
	xtreePos_t handle;

	if (head == NULL)
		return;
................................................................................
	fprintf(output, "</TR>\n");
	fprintf(output, "<TR><td>&nbsp;</td><TD COLSPAN=%d><HR WIDTH=\"100%%\"></TD></TR>\n\n", hostcount);

	/* Create a tree indexed by the testname, and holding the show/noshow status of each test */
	for (h = head, hidx = 0; (h); h = h->next, hidx++) {
		for (e = h->entries; (e); e = e->next) {
			vprec_t *itm;
			char *hptr;

			handle = xtreeFind(vptree, e->column->name);
			if (handle == xtreeEnd(vptree)) {
				itm = (vprec_t *)malloc(sizeof(vprec_t));
				itm->testname = e->column->name;
				itm->hosts = (host_t **)calloc(hostcount, sizeof(host_t *));
				itm->entries = (entry_t **)calloc(hostcount, sizeof(entry_t *));
................................................................................
		dispsummary_t *s2;

		/* Do we already have it ? */
		for (newhost = sumhosts; (newhost && (strcmp(s->row, newhost->hostname) != 0) ); newhost = newhost->next);

		if (newhost == NULL) {
			/* New summary "host" */
			newhost = init_host(s->row, 1, NULL, NULL, NULL, NULL, "", 0, 0.0, 0, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);

			/* Insert into sorted host list */
			if ((!sumhosts) || (strcmp(newhost->hostname, sumhosts->hostname) < 0)) {
				/* Empty list, or new entry goes before list head item */
				newhost->next = sumhosts;
				sumhosts = newhost;
			}
................................................................................
		}
		p = strtok(NULL, "\t ");
	}

	xfree(extensions);
}

int do_nongreen_page(char *nssidebarfilename, int summarytype)
{
	xymongen_page_t	nongreenpage;
	FILE		*output = NULL;
	FILE		*rssoutput = NULL;
	char		filename[PATH_MAX];
	char		tmpfilename[PATH_MAX];
	char		rssfilename[PATH_MAX];
................................................................................
				}
			}
		}
	}

	switch (summarytype) {
	  case PAGE_NONGREEN:
		sprintf(filename, "nongreen%s", htmlextension);
		sprintf(rssfilename, "nongreen%s", rssextension);
		break;
	  case PAGE_CRITICAL:
		sprintf(filename, "critical%s", htmlextension);
		sprintf(rssfilename, "critical%s", rssextension);
		break;
	}

	sprintf(tmpfilename, "%s.tmp", filename);
	output = fopen(tmpfilename, "w");
	if (output == NULL) {
		errprintf("Cannot create file %s: %s\n", tmpfilename, strerror(errno));







|







 







<







 







|







 







|







 







|
|


|
|







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
...
363
364
365
366
367
368
369

370
371
372
373
374
375
376
...
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
....
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
....
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
	 * I.e. it generates buttons and links to all the hosts for
	 * a test, and the host docs.
	 */

	host_t	*h;
	entry_t	*e;
	char	*xymonskin;
	int	hostcount = 0;
	int	width;
	int	hidx;
	void	*vptree;
	xtreePos_t handle;

	if (head == NULL)
		return;
................................................................................
	fprintf(output, "</TR>\n");
	fprintf(output, "<TR><td>&nbsp;</td><TD COLSPAN=%d><HR WIDTH=\"100%%\"></TD></TR>\n\n", hostcount);

	/* Create a tree indexed by the testname, and holding the show/noshow status of each test */
	for (h = head, hidx = 0; (h); h = h->next, hidx++) {
		for (e = h->entries; (e); e = e->next) {
			vprec_t *itm;


			handle = xtreeFind(vptree, e->column->name);
			if (handle == xtreeEnd(vptree)) {
				itm = (vprec_t *)malloc(sizeof(vprec_t));
				itm->testname = e->column->name;
				itm->hosts = (host_t **)calloc(hostcount, sizeof(host_t *));
				itm->entries = (entry_t **)calloc(hostcount, sizeof(entry_t *));
................................................................................
		dispsummary_t *s2;

		/* Do we already have it ? */
		for (newhost = sumhosts; (newhost && (strcmp(s->row, newhost->hostname) != 0) ); newhost = newhost->next);

		if (newhost == NULL) {
			/* New summary "host" */
			newhost = init_host(s->row, 1, NULL, NULL, NULL, NULL, 0,0,0,0, 0, 0.0, 0, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);

			/* Insert into sorted host list */
			if ((!sumhosts) || (strcmp(newhost->hostname, sumhosts->hostname) < 0)) {
				/* Empty list, or new entry goes before list head item */
				newhost->next = sumhosts;
				sumhosts = newhost;
			}
................................................................................
		}
		p = strtok(NULL, "\t ");
	}

	xfree(extensions);
}

int do_nongreen_page(char *nssidebarfilename, int summarytype, char *filenamebase)
{
	xymongen_page_t	nongreenpage;
	FILE		*output = NULL;
	FILE		*rssoutput = NULL;
	char		filename[PATH_MAX];
	char		tmpfilename[PATH_MAX];
	char		rssfilename[PATH_MAX];
................................................................................
				}
			}
		}
	}

	switch (summarytype) {
	  case PAGE_NONGREEN:
		sprintf(filename, "%s%s", filenamebase, htmlextension);
		sprintf(rssfilename, "%s%s", filenamebase, rssextension);
		break;
	  case PAGE_CRITICAL:
		sprintf(filename, "%s%s", filenamebase, htmlextension);
		sprintf(rssfilename, "%s%s", filenamebase, rssextension);
		break;
	}

	sprintf(tmpfilename, "%s.tmp", filename);
	output = fopen(tmpfilename, "w");
	if (output == NULL) {
		errprintf("Cannot create file %s: %s\n", tmpfilename, strerror(errno));

Changes to xymongen/pagegen.h.

40
41
42
43
44
45
46
47
48
49
extern char *logcritstatus;
extern int  critonlyreds;
extern int  wantrss;

extern void select_headers_and_footers(char *prefix);
extern void do_one_page(xymongen_page_t *page, dispsummary_t *sums, int embedded);
extern void do_page_with_subs(xymongen_page_t *curpage, dispsummary_t *sums);
extern int  do_nongreen_page(char *nssidebarfilename, int summarytype);

#endif







|


40
41
42
43
44
45
46
47
48
49
extern char *logcritstatus;
extern int  critonlyreds;
extern int  wantrss;

extern void select_headers_and_footers(char *prefix);
extern void do_one_page(xymongen_page_t *page, dispsummary_t *sums, int embedded);
extern void do_page_with_subs(xymongen_page_t *curpage, dispsummary_t *sums);
extern int  do_nongreen_page(char *nssidebarfilename, int summarytype, char *filenamebase);

#endif

Changes to xymongen/xymongen.1.

1
2
3
4
5
6
7
8
...
209
210
211
212
213
214
215



216
217
218
219
220
221
222
...
679
680
681
682
683
684
685







686
687
688
689
.TH XYMONGEN 1 "Version 4.3.7: 13 Dec 2011" "Xymon"
.SH NAME
xymongen \- Xymon webpage generator
.SH SYNOPSIS
.B "xymongen -?"
.br
.B "xymongen --help"
.br
................................................................................
.sp
.IP "--nongreen-ignorepurples"
Deprecated, use "--nongreen-colors" instead.
.sp
.IP "--nongreen-ignoredialups"
Ignore all dialup hosts on the "All non-green" page, including the eventlog.
.sp



.IP "--no-nongreen"
Do not generate the "All non-green" page.
.sp
.IP "--includecolumns=test[,test]"
Always include these columns on "All non-green" page Will include certain columns on 
the nongreen.html page, regardless of its color. Normally, nongreen.html drops a 
test-column, if all tests are green. This can be used e.g. to always have 
................................................................................
files anywhere you like - perhaps on another machine - and then move
them to the webserver later on.

Note how the 
.I date(1)
utility is used to calculate the start- and end-time parameters.








.SH "SEE ALSO"
hosts.cfg(5), xymonserver.cfg(5), tasks.cfg(5), report.cgi(1), 
snapshot.cgi(1), xymon(7)

|







 







>
>
>







 







>
>
>
>
>
>
>




1
2
3
4
5
6
7
8
...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
.TH XYMONGEN 1 "Version 4.3.11: 21 Apr 2013" "Xymon"
.SH NAME
xymongen \- Xymon webpage generator
.SH SYNOPSIS
.B "xymongen -?"
.br
.B "xymongen --help"
.br
................................................................................
.sp
.IP "--nongreen-ignorepurples"
Deprecated, use "--nongreen-colors" instead.
.sp
.IP "--nongreen-ignoredialups"
Ignore all dialup hosts on the "All non-green" page, including the eventlog.
.sp
.IP "--no-pages"
Do not generate the normal pages (normally used to generate only the non-green page).
.sp
.IP "--no-nongreen"
Do not generate the "All non-green" page.
.sp
.IP "--includecolumns=test[,test]"
Always include these columns on "All non-green" page Will include certain columns on 
the nongreen.html page, regardless of its color. Normally, nongreen.html drops a 
test-column, if all tests are green. This can be used e.g. to always have 
................................................................................
files anywhere you like - perhaps on another machine - and then move
them to the webserver later on.

Note how the 
.I date(1)
utility is used to calculate the start- and end-time parameters.

.SH "ENVIRONMENT VARIABLES"
.IP BOARDFILTER
Filter used to select what hosts / tests are included in the webpages, by
filtering the data retrieved from xymond vi the xymondboard command. See
.I xymon(1)
for details on the filter syntax. By default, no filtering is done.

.SH "SEE ALSO"
hosts.cfg(5), xymonserver.cfg(5), tasks.cfg(5), report.cgi(1), 
snapshot.cgi(1), xymon(7)

Changes to xymongen/xymongen.c.

111
112
113
114
115
116
117
118
119
120
121
122
123








124
125
126
127
128
129
130
...
431
432
433
434
435
436
437
438






439
440
441
442
443








444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
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
...
629
630
631
632
633
634
635



636
637
638
639
640
641
642
643
644
645
646
647
648
	/* Setup values from env. vars that may be overridden via command-line options */
	if (xgetenv("XYMONPAGECOLREPEAT")) {
		int i = atoi(xgetenv("XYMONPAGECOLREPEAT"));

		if (i > 0) maxrowsbeforeheading = i;
	}

	libxymon_init(argv[0]);
	for (i = 1; (i < argc); i++) {
		if ( (strcmp(argv[i], "--hobbitd") == 0)       ||
		     (argnmatch(argv[i], "--purplelifetime=")) ||
		     (strcmp(argv[i], "--nopurple") == 0)      ) {
			/* Deprecated */








		}

		else if (argnmatch(argv[i], "--ignorecolumns=")) {
			char *lp = strchr(argv[i], '=');
			ignorecolumns = (char *) malloc(strlen(lp)+2);
			sprintf(ignorecolumns, ",%s,", (lp+1));
		}
................................................................................
			if (lp) {
				logcritstatus = strdup(lp+1);
			}
			else logcritstatus = "critical";
		}
		else if (strcmp(argv[i], "--timing") == 0) {
			timing = 1;
		}






		else if (strcmp(argv[i], "--loadhostsfromxymond") == 0) {
			loadhostsfromxymond = 1;
		}
		else if (standardoption(argv[i])) {
			if (showhelp) {








				printf("Usage: %s [options] [WebpageDirectory]\n", argv[0]);
				printf("Options:\n");
				printf("    --ignorecolumns=test[,test] : Completely ignore these columns\n");
				printf("    --critical-reds-only        : Only show red statuses on the Critical page\n");
				printf("    --nongreen-ignorecolumns=test[,test]: Ignore these columns for the non-green page\n");
				printf("    --nongreen-ignorepurples         : Ignore all-purple hosts on non-green page\n");
				printf("    --includecolumns=test[,test]: Always include these columns on non-green page\n");
				printf("    --max-eventcount=N          : Max number of events to include in eventlog\n");
				printf("    --max-eventtime=N           : Show events that occurred within the last N minutes\n");
				printf("    --eventignore=test[,test]   : Columns to ignore in non-green event-log display\n");
				printf("    --no-eventlog               : Do not generate the non-green eventlog display\n");
				printf("    --no-acklog                 : Do not generate the non-green ack-log display\n");
				printf("    --no-pages                  : Generate only the nongreen and critical pages\n");
				printf("    --docurl=documentation-URL  : Hostnames link to a general (dynamic) web page for docs\n");
				printf("    --doc-window                : Open doc-links in a new browser window\n");
				printf("    --htmlextension=.EXT        : Sets filename extension for generated file (default: .html\n");
				printf("    --report[=COLUMNNAME]       : Send a status report about the running of xymongen\n");
				printf("    --reportopts=ST:END:DYN:STL : Run in Xymon Reporting mode\n");
				printf("    --csv=FILENAME              : For Xymon Reporting, output CSV file\n");
				printf("    --csvdelim=CHARACTER        : Delimiter in CSV file output (default: comma)\n");
				printf("    --snapshot=TIME             : Snapshot mode\n");
				printf("\nPage layout options:\n");
				printf("    --pages-first               : Put page- and subpage-links before hosts (default)\n");
				printf("    --pages-last                : Put page- and subpage-links after hosts\n");
				printf("    --subpagecolumns=N          : Number of columns for links to pages and subpages\n");
				printf("    --maxrows=N                 : Repeat column headings for every N hosts shown\n");
				printf("    --recentgifs                : Use xxx-recent.gif icons for newly changed tests\n");
				printf("    --sort-group-only-items     : Display group-only items in alphabetical order\n");
				printf("    --page-title=TITLE          : Set a default page title for all pages\n");
				printf("    --dialupskin=URL            : Use a different icon skin for dialup tests\n");
				printf("    --reverseskin=URL           : Use a different icon skin for reverse tests\n");
				printf("    --pagetitle-links           : Make page- and subpage-titles act as links\n");
				printf("    --pagetext-headings         : Use page texts as headings\n");
				printf("    --no-underline-headings     : Do not underline the page headings\n");
				printf("\nStatus propagation control options:\n");
				printf("    --noprop=test[,test]        : Disable upwards status propagation when YELLOW\n");
				printf("    --nopropred=test[,test]     : Disable upwards status propagation when RED or YELLOW\n");
				printf("    --noproppurple=test[,test]  : Disable upwards status propagation when PURPLE\n");
				printf("\nAlternate pageset generation support:\n");
				printf("    --pageset=SETNAME           : Generate non-standard pageset with tag SETNAME\n");
				printf("    --template=TEMPLATE         : template for header and footer files\n");
				printf("\nAlternate output formats:\n");
				printf("    --wml[=test1,test2,...]     : Generate a small (All nongreen-style) WML page\n");
				printf("    --nstab=FILENAME            : Generate a Netscape Sidebar feed\n");
				printf("    --nslimit=COLOR             : Minimum color to include on Netscape sidebar\n");
				printf("    --rss                       : Generate a RSS/RDF feed of alerts\n");
				printf("    --rssextension=.EXT         : Sets filename extension for RSS files (default: .rss\n");
				printf("    --rssversion={0.91|0.92|1.0|2.0} : Specify RSS/RDF version (default: 0.91)\n");
				printf("    --rsslimit=COLOR            : Minimum color to include on RSS feed\n");
				printf("\nDebugging/troubleshooting options:\n");
				printf("    --timing                    : Collect timing information\n");
				printf("    --debug                     : Debugging information\n");
				printf("    --version                   : Show version information\n");
				printf("    --purplelog=FILENAME        : Create a log of purple hosts and tests\n");
				exit(0);
			}
		}
		else if (argnmatch(argv[i], "-")) {
			errprintf("Unknown option : %s\n", argv[i]);
		}

		else {
			/* Last argument is pagedir */
................................................................................
	if (reportstart) {
		/* Reports end here */
		return 0;
	}

	/* The full summary page - nongreen.html */
	if (do_nongreen) {



		nongreen_color = do_nongreen_page(nssidebarfilename, PAGE_NONGREEN);
		add_timestamp("Non-green page generation done");
	}

	/* Reduced summary (alerts) page - critical.html */
	critical_color = do_nongreen_page(NULL, PAGE_CRITICAL);
	add_timestamp("Critical page generation done");

	if (snapshot) {
		/* Snapshots end here */
		return 0;
	}








<





>
>
>
>
>
>
>
>







 








>
>
>
>
>
>



<
<
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<







 







>
>
>
|




|







111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454


455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
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
516
517

518
519
520
521
522
523
524
...
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
	/* Setup values from env. vars that may be overridden via command-line options */
	if (xgetenv("XYMONPAGECOLREPEAT")) {
		int i = atoi(xgetenv("XYMONPAGECOLREPEAT"));

		if (i > 0) maxrowsbeforeheading = i;
	}


	for (i = 1; (i < argc); i++) {
		if ( (strcmp(argv[i], "--hobbitd") == 0)       ||
		     (argnmatch(argv[i], "--purplelifetime=")) ||
		     (strcmp(argv[i], "--nopurple") == 0)      ) {
			/* Deprecated */
		}
		else if (argnmatch(argv[i], "--env=")) {
			char *lp = strchr(argv[i], '=');
			loadenv(lp+1, envarea);
		}
		else if (argnmatch(argv[i], "--area=")) {
			char *lp = strchr(argv[i], '=');
			envarea = strdup(lp+1);
		}

		else if (argnmatch(argv[i], "--ignorecolumns=")) {
			char *lp = strchr(argv[i], '=');
			ignorecolumns = (char *) malloc(strlen(lp)+2);
			sprintf(ignorecolumns, ",%s,", (lp+1));
		}
................................................................................
			if (lp) {
				logcritstatus = strdup(lp+1);
			}
			else logcritstatus = "critical";
		}
		else if (strcmp(argv[i], "--timing") == 0) {
			timing = 1;
		}
		else if (strcmp(argv[i], "--debug") == 0) {
			debug = 1;
		}
		else if (strcmp(argv[i], "--no-update") == 0) {
			dontsendmessages = 1;
		}
		else if (strcmp(argv[i], "--loadhostsfromxymond") == 0) {
			loadhostsfromxymond = 1;
		}


		else if (strcmp(argv[i], "--version") == 0) {
			printf("xymongen version %s\n", VERSION);
			printf("\n");
			exit(0);
		}

		else if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-?") == 0)) {
			printf("xymongen for Xymon version %s\n\n", VERSION);
			printf("Usage: %s [options] [WebpageDirectory]\n", argv[0]);
			printf("Options:\n");
			printf("    --ignorecolumns=test[,test] : Completely ignore these columns\n");
			printf("    --critical-reds-only        : Only show red statuses on the Critical page\n");
			printf("    --nongreen-ignorecolumns=test[,test]: Ignore these columns for the non-green page\n");
			printf("    --nongreen-ignorepurples         : Ignore all-purple hosts on non-green page\n");
			printf("    --includecolumns=test[,test]: Always include these columns on non-green page\n");
		        printf("    --max-eventcount=N          : Max number of events to include in eventlog\n");
		        printf("    --max-eventtime=N           : Show events that occurred within the last N minutes\n");
			printf("    --eventignore=test[,test]   : Columns to ignore in non-green event-log display\n");
			printf("    --no-eventlog               : Do not generate the non-green eventlog display\n");
			printf("    --no-acklog                 : Do not generate the non-green ack-log display\n");
			printf("    --no-pages                  : Generate only the nongreen and critical pages\n");
			printf("    --docurl=documentation-URL  : Hostnames link to a general (dynamic) web page for docs\n");
			printf("    --doc-window                : Open doc-links in a new browser window\n");
			printf("    --htmlextension=.EXT        : Sets filename extension for generated file (default: .html\n");
			printf("    --report[=COLUMNNAME]       : Send a status report about the running of xymongen\n");
			printf("    --reportopts=ST:END:DYN:STL : Run in Xymon Reporting mode\n");
			printf("    --csv=FILENAME              : For Xymon Reporting, output CSV file\n");
			printf("    --csvdelim=CHARACTER        : Delimiter in CSV file output (default: comma)\n");
			printf("    --snapshot=TIME             : Snapshot mode\n");
			printf("\nPage layout options:\n");
			printf("    --pages-first               : Put page- and subpage-links before hosts (default)\n");
			printf("    --pages-last                : Put page- and subpage-links after hosts\n");
			printf("    --subpagecolumns=N          : Number of columns for links to pages and subpages\n");
			printf("    --maxrows=N                 : Repeat column headings for every N hosts shown\n");
			printf("    --recentgifs                : Use xxx-recent.gif icons for newly changed tests\n");
			printf("    --sort-group-only-items     : Display group-only items in alphabetical order\n");
			printf("    --page-title=TITLE          : Set a default page title for all pages\n");
			printf("    --dialupskin=URL            : Use a different icon skin for dialup tests\n");
			printf("    --reverseskin=URL           : Use a different icon skin for reverse tests\n");
			printf("    --pagetitle-links           : Make page- and subpage-titles act as links\n");
			printf("    --pagetext-headings         : Use page texts as headings\n");
			printf("    --no-underline-headings     : Do not underline the page headings\n");
			printf("\nStatus propagation control options:\n");
			printf("    --noprop=test[,test]        : Disable upwards status propagation when YELLOW\n");
			printf("    --nopropred=test[,test]     : Disable upwards status propagation when RED or YELLOW\n");
			printf("    --noproppurple=test[,test]  : Disable upwards status propagation when PURPLE\n");
			printf("\nAlternate pageset generation support:\n");
			printf("    --pageset=SETNAME           : Generate non-standard pageset with tag SETNAME\n");
			printf("    --template=TEMPLATE         : template for header and footer files\n");
			printf("\nAlternate output formats:\n");
			printf("    --wml[=test1,test2,...]     : Generate a small (All nongreen-style) WML page\n");
			printf("    --nstab=FILENAME            : Generate a Netscape Sidebar feed\n");
			printf("    --nslimit=COLOR             : Minimum color to include on Netscape sidebar\n");
			printf("    --rss                       : Generate a RSS/RDF feed of alerts\n");
			printf("    --rssextension=.EXT         : Sets filename extension for RSS files (default: .rss\n");
			printf("    --rssversion={0.91|0.92|1.0|2.0} : Specify RSS/RDF version (default: 0.91)\n");
			printf("    --rsslimit=COLOR            : Minimum color to include on RSS feed\n");
			printf("\nDebugging/troubleshooting options:\n");
			printf("    --timing                    : Collect timing information\n");
			printf("    --debug                     : Debugging information\n");
			printf("    --version                   : Show version information\n");
			printf("    --purplelog=FILENAME        : Create a log of purple hosts and tests\n");
			exit(0);

		}
		else if (argnmatch(argv[i], "-")) {
			errprintf("Unknown option : %s\n", argv[i]);
		}

		else {
			/* Last argument is pagedir */
................................................................................
	if (reportstart) {
		/* Reports end here */
		return 0;
	}

	/* The full summary page - nongreen.html */
	if (do_nongreen) {
		nongreen_color = do_nongreen_page(nssidebarfilename, PAGE_NONGREEN, "nongreen");
		nongreencolors = (nongreencolors & ~(1 << COL_YELLOW));
		nongreencolors = (nongreencolors & ~(1 << COL_PURPLE));
		nongreen_color = do_nongreen_page(nssidebarfilename, PAGE_NONGREEN, "red");
		add_timestamp("Non-green page generation done");
	}

	/* Reduced summary (alerts) page - critical.html */
	critical_color = do_nongreen_page(NULL, PAGE_CRITICAL, "critical");
	add_timestamp("Critical page generation done");

	if (snapshot) {
		/* Snapshots end here */
		return 0;
	}