scc-log2html(1)
NAME
scc-log2html - convert a SCC-logbook to HTML-format
RELEASE
scc 1.23.185
SYNOPSIS
scc-log2html [ -h|--help ] [ -s|--standalone ] <name>
DESCRIPTION
This program reads a SCC-logbook from stdin and converts it to HTML-
format on stdout. Refer to scc(4) for a detailed description of
SCC-logbook. An empty logbook results in an empty html-file.
The html-file consists of a table with entries for each run of scc.
For reported differences in the logbook, the menu contains an URL
pointing to the corresponding report.
The logbook contains DIV-tags with the following nested classes:
- SCC_LOG
- SCC_LOG_NAV
- SCC_LOG_SUMMARY
- SCC_LOG_STATS
- SCC_LOG_ENTRY
The sylesheet style.css in /var/opt/scc/data controls the markup.
OPTIONS
-h|--help Display the syntax and exit.
-s|--standalone Embed the stylesheet in the html-data and do not
show "externel" links to snapshot and index.html.
Use this option before transferring the html
version of the logbook to a user.
ARGUMENTS
<name> name of the host to convert the SCC-snapshot for
DIAGNOSTICS
This program writes the following message to stderr:
Syntax error, use: scc-log2html [ -h|--help ] [ -s|--standalone ] <name>
A syntax error was detected and reported.
scc-log2html: insufficient permissions to write in data directory: <data_dir>
To run this program, log in as the owner of the directory.
RETURN VALUE
Upon completion, the program returns one of the following values:
0 successful completion
1 Syntax error
2 Runtime error
EXTERNAL INFLUENCES
Use environment variable SCC_DATA to specify an alternative directory
for the SCC data files. Should be an absolute path.
COPYRIGHT
scc-log2html is free software under the terms of the GNU General Public
License. Copyright (C) 2001-2004 Open Challenge B.V.,
2004-2005 OpenEyeT Professional Services, 2005-2015 QNH.
FILES
/var/opt/scc/data/style.css - stylesheet
SEE ALSO
scc(1), scc-cmp(1), scc-collect(1), scc-log(1), scc-log2html(1),
scc-plugin(1), scc-snap2html(1), scc(4), scc(5)
VERSION
$Revision: 5917 $
) ;;
echo "${ProgName}: alternative SCC_DATA (${SCC_DATA}) should be an absolute path" >&2
xit 2;;
ac
Perform the security settings before calling any program.
TH=/sbin:/usr/sbin:/usr/bin:/bin; export PATH
port TMPDIR=${SCC_TMP}
port TMP=${SCC_TMP}
port SHELL=/bin/sh
[ ! -w ${SCC_DATA} ]
en
cho "${ProgName}: insufficient permissions to write in data directory: ${SCC_DATA}" >&2
xit 2
${SCC_TMP}
ask 077
D_LINE="${ProgName} [ -h|--help ] [ -s|--standalone ] <name>"
NTAX_ERROR="Syntax error, use: ${CMD_LINE}"
andalone=""
ile [ $# -gt 0 ]
ase "${1}" in
s|--standalone) standalone="yes"
shift 1;;
h|--help) echo "${CMD_LINE}"
exit 0;;
*) echo "${SYNTAX_ERROR}" >&2
exit 1;;
) break;;
sac
ne
[ $# -ne 1 ]
en
cho "${SYNTAX_ERROR}" >&2
xit 1
${SCC_BIN}/scc_modules/scc_utils
-r ${SCC_CONF}/scc-localize ] && . ${SCC_CONF}/scc-localize
ndom="$(get_RANDOM)"
port TMP_FILE=${SCC_TMP}/scc_log_html_$$_${random}
ap 'rm -f ${TMP_FILE}' 0
ap "exit 2" 1 2 3 15
Replace special HTML-characters in input.
d -e 's/&/\&/g' \
e 's/</\</g' \
e 's/>/\>/g' \
e "s/'/\'/g" \
e 's/"/\"/g' >${TMP_FILE}
[ ! -s ${TMP_FILE} ]
en
xit 0
In standalone mode and with only one run, we do not generate statistics.
ngle_run=""
[ "${standalone}" ]
en
irst_run_time="$(head -n 1 ${TMP_FILE} | sed -e 's/:[^0-9].*//')"
ast_run_time="$(tail -n 1 ${TMP_FILE} | sed -e 's/:[^0-9].*//')"
f [ "${first_run_time}" = "${last_run_time}" ]
hen
single_run="yes"
i
BLE_TAG="<TABLE CLASS=SCC SUMMARY=\"Summary of scc-runs\" BORDER CELLSPACING=1 CELLPADDING=4>"
P_NAME="<A NAME=cfg_top></A>"
P_URL="<A HREF=\"#cfg_top\">Top</A> "
ho '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'
ho "<HTML lang=\"en\">"
ho "<HEAD>"
[ -z "${standalone}" ]
en
cho '<LINK HREF="style.css" REL="stylesheet" TYPE="text/css">'
se
f [ -f "${SCC_DATA}/style.css" ]
hen
echo '<style TYPE="text/css">'
cat "${SCC_DATA}/style.css"
echo "</style>"
i
ho "<TITLE>Logbook: $1</TITLE>"
ho "</HEAD>"
ho "<BODY>"
ho "<DIV class=SCC_LOG>";
ho "${TOP_NAME}"
ho "<H1>Logbook: ${1}</H1>"
DO NOT CHANGE THE FOLLOWING HTML-CODE WITHOUT CONSULTING scc.cgi IN scc-srv
[ -z "${single_run}" ]
en
cho "<DIV class=SCC_LOG_NAV>";
cho "<H2>"
f [ -z "${standalone}" ]
hen
echo " <A HREF=\"index.html\">Home</A> "
echo " <A HREF=\"scc.${1}.html\">Configuration</A> "
i
cho ' <A HREF="#cfg_statistics">Statistics</A>'
cho "</H2>"
cho "</DIV><!-- class=SCC_LOG_NAV -->";
cho "<H3>Summary of runs of SCC</H3>"
se
cho "<H2>Run of SCC</H2>"
Build a table with URL's to reported differences in the logbook.
Use the date/time of the run as the ID for HREF and NAME.
Sort the data reverse to show the most recent change at the top of the table.
Check the code in scc-log for the specific layout of the logbook.
k -F: '/:result::/ {
stat_cnt_runs++;
if ( length( prev_res ) )
{
# restart or identical, no number of differences.
print prev_res ":" ":" prev_runtime ":" prev_remark;
prev_remark="";
prev_runtime="";
}
prev_res=$0;
}
:remark::/ {
# A remark can contain ":", syntax of a line is: <date>:<time>:remark::<remark>
prev_remark = $5;
for ( i = 6; i <= NF; i++ )
{
prev_remark = sprintf( "%s: %s", prev_remark, $i );
}
}
:runtime::/ {
# Use a separate counter as older versions of SCC did not record the runtime.
stat_runtime_cnt++;
stat_runtime_total+=$NF;
# The min/max urls from the statistics table refer to the entire table with the runs: prefix = "back"
if ( $NF > stat_runtime_max )
{
stat_runtime_max = $NF;
runtime_max_date = $1;
runtime_max_time = $2;
}
if ( $NF < stat_runtime_min || stat_runtime_min == 0 )
{
stat_runtime_min = $NF;
runtime_min_date = $1;
runtime_min_time = $2;
}
prev_runtime=$NF;
}
:count::/ {
stat_change_cnt++;
stat_change_total+=$NF;
# The min/max urls from the statistics table refer to the changes: prefix = "log"
if ( $NF > stat_change_max )
{
stat_change_max = $NF;
change_max_date = $1;
change_max_time = $2;
}
if ( $NF < stat_change_min || stat_change_min == 0 )
{
stat_change_min = $NF;
change_min_date = $1;
change_min_time = $2;
}
# changes detected, report
print prev_res ":" $NF ":" prev_runtime ":" prev_remark;
prev_res=""
prev_remark=""
}
D {
# unreported results?
if ( length( prev_res ) )
{
print prev_res ":" ":" prev_runtime ":" prev_remark;
}
if ( stat_cnt_runs == 0 )
{
stat_cnt_runs=1;
stat_runtime_cnt=1;
}
# Prefix the statistics lines with 0 to put them at the end of the data after the reverse sort we are going to perform:
printf( "0:9:runs total : %d\n", stat_cnt_runs );
printf( "0:8:runs with changes : %d\n", stat_change_cnt );
printf( "0:7:runs perc. changes: %d\n", ( 100 * stat_change_cnt ) / stat_cnt_runs );
printf( "0:6:change count min. : %d:log:%s:%s\n", stat_change_min, change_min_date, change_min_time );
printf( "0:5:change count max. : %d:log:%s:%s\n", stat_change_max, change_max_date, change_max_time );
if ( stat_change_cnt == 0 )
{
stat_change_cnt = 1;
}
printf( "0:4:change count average: %d\n", stat_change_total / stat_change_cnt );
printf( "0:3:runtime min. : %d:back:%s:%s\n", stat_runtime_min, runtime_min_date, runtime_min_time );
printf( "0:2:runtime max. : %d:back:%s:%s\n", stat_runtime_max, runtime_max_date, runtime_max_time );
printf( "0:1:runtime average : %d\n", stat_runtime_total / stat_runtime_cnt );
}' ${TMP_FILE} |
rt -r |
k -F":" '{
# We produce both the table with all runs and the table with the statistics.
# Start with the table with all runs.
# The variable u is not initialized in a BEGIN-clause.
# Therefore we check for the first record.
if ( NR == 1 )
{
print "<DIV class=SCC_LOG_SUMMARY>";
print u;
print "<THEAD>";
print " <TR class=Odd>";
print " <TH>Date</TH>";
print " <TH>Time</TH>";
print " <TH>Runtime</TH>";
print " <TH>Result</TH>";
print " <TH>Count</TH>";
print " <TH>Remark</TH>";
print " </TR>";
print "</THEAD>";
print "<TBODY>";
tr_c = "Even";
}
0:/ {
# Process the statistics:
# Format of the input data is:
#0:<order>:<label>:<value>[:<prefix>:<date>:<time>]
if ( statistics == 0 ) # No heading yet?
{
print "</TBODY>";
print "</TABLE>";
print "</DIV><!-- class=SCC_LOG_SUMMARY -->";
statistics=1; # Heading done!
if ( length( single_run ) )
{
next;
}
print "<HR>";
print "<DIV class=SCC_LOG_STATS>";
print "<A NAME=cfg_statistics></A>"
printf( "<H3>%sStatistics</H3>\n", t );
print u;
print "<THEAD>";
print " <TR class=Odd>";
print " <TH>Category</TH>";
print " <TH>Value</TH>";
print " <TH>Date</TH>";
print " </TR>";
print "</THEAD>";
print "<TBODY>";
s_tr="Even";
}
if ( length( single_run ) )
{
next;
}
print "<TR class=" s_tr ">";
if ( s_tr != "Even" )
{
s_tr = "Even";
}
else
{
s_tr = "Odd";
}
print " <TD class=Even>" $3 "</TD>"; # Category
printf( " <TD class=Odd align=right>%s</TD>\n", $4 ); # Value
if ( length( $5 ) > 0 )
{
printf( " <TD class=Even><A HREF=\"#%s_%s_%s\">%s %s</A></TD>\n", $5, $6, $7, $6, $7 ); # Date
}
else
{
printf( " <TD class=Even> </TD>\n" ); # No date
}
print "</TR>";
next;
{
Show data of a run.
Format of the input is:
<date>:<time>:result::different:<count>:<runtime>:<remark>
f ( $5 == "different" )
print "<TR class=" tr_c "_Emp>";
lse
print "<TR class=" tr_c ">";
f ( tr_c != "Even" )
tr_c = "Even";
lse
tr_c = "Odd";
rintf( " <TD class=Even><A NAME=\"back_%s_%s\"></A>%s</TD>\n", $1, $2, $1 ); # Date
rint " <TD class=Odd>" $2 "</TD>"; # Time
f ( length( $7 ) > 0 ) # Runtime available?
printf( " <TD class=Even align=right>%s</TD>\n", $7 );
lse
print " <TD class=Even> </TD>";
f ( $5 == "different" ) # Result
printf( " <TD class=Odd_Emp><A HREF=\"#log_%s_%s\" TITLE=\"%s %s\">%s</A></TD>\n", $1, $2, $1, $2, $5 );
lse
printf( " <TD class=Odd>%s</TD>\n", $5 );
f ( length( $6 ) > 0 ) # Count available?
printf( " <TD class=Even align=right>%s</TD>\n", $6 );
lse
print " <TD class=Even> </TD>";
emark = $8; # Possibly contains ":"
or ( i = 9; i <= NF; i++ )
remark = sprintf( "%s: %s", remark, $i );
f ( length( remark ) > 0 )
printf( " <TD class=Odd_Emp align=left>%s</TD>\n", remark );
lse
print " <TD class=Odd> </TD>";
rint "</TR>";
}
D {
if ( length( single_run ) == 0 )
{
print "</TBODY>";
print "</TABLE>";
print "</DIV><!-- class=SCC_LOG_STATS -->";
}
' single_run="${single_run}" t="${TOP_URL}" u="${TABLE_TAG}"
When sorting the logdata, we want to preserve the order of the data within each single run.
As we sort descending, we use <total_line_nr> - <current_record_nr>.
First determine the total_line_nr:
tal_cnt="$(wc -l <${TMP_FILE})"
Now the table is present, we show the data.
Use the date/time of the run as the ID for HREF and NAME.
k -F: '{
# Sort the log file, most recent run first,
# within the run keep the data in the order of the log file.
log_date=$1;
log_time=$2;
gsub( "-", "", log_date );
gsub( /\./, "", log_time );
printf( "%s:%s:%010.10d:%s\n", log_date, log_time, total - NR, $0 );
' total="${total_cnt}" ${TMP_FILE} |
rt -r |
d -e 's/^[0-9]*:[0-9]*:[0-9]*://' |
k -F":" 'BEGIN { first_log_entry = 1; }
:result::different$/ {
if ( show_data )
{
print "</PRE>"; # end of previously showed data
}
show_data=1; # indicate that we are going to show differences
prev_class=""; # reset class-identifier for this run
print "<HR>";
if ( first_log_entry )
{
print "<DIV class=SCC_LOG_ENTRY>";
first_log_entry=0;
}
printf( "<H3>%s<A HREF=\"#back_%s_%s\" TITLE=\"%s %s\">Runs</A> ", u, $1, $2, $1, $2 );
printf( "<A NAME=\"log_%s_%s\">Differences at: %s %s</A></H3>\n", $1, $2, $1, $2 );
print "<PRE>";
next;
}
:result::identical$|:result::.re.start$/ {
if ( show_data )
{
print "</PRE>"; # end of previously showed data
}
show_data=0; # the are no differences: do not show data
next;
}
:data::/ {
if ( show_data )
{
# Do not show the classification on each line, only once in bold format.
change=$5; # old/new or ctx for unchanged data with context diff
# $6 is empty to separate changed data from the classification
class=$7;
for ( i = 8; length( $i ) > 0; i++ )
{
class=sprintf( "%s - %s", class, $i );
}
if ( class != prev_class )
{
print "</PRE>";
print "<H4>" class "</H4>";
print "<PRE>";
prev_class=class;
}
if ( change == "ctx" )
{
printf( "<span class=\"%s\"> ", change );
}
else
{
printf( "<span class=\"%s\">%s: ", change, change );
}
for ( i++; i < NF; i++ )
{
printf( "%s:", $i );
}
print $i "</span>";
}
next;
}
{
# No data, classifications:
# possible classifications are: count, remark, previous date and time
if ( show_data )
{
printf( "%-30.30s: %s\n", $3, $5 );
}
next;
}
D {
if ( show_data )
{
print "</PRE>"; # end of previously showed data
}
print "<HR>";
if ( first_log_entry == 0 ) # Have any log-entries been printed?
{
print "</DIV><!-- class=SCC_LOG_ENTRY -->"; # Mark the end of all log-entries.
}
' u="${TOP_URL}"
-f ${TMP_FILE}
ho "<P>Generated by SCC version 1.23.185 (© <A HREF=\"http://www.qnh.eu\">QNH</A>) on $(date)</P>"
ho "</DIV><!-- class=SCC_LOG -->";
ho "</BODY>"
ho "</HTML>"
it 0