Re: radius: two Stop records?

Johan Persson (Johan.Persson@abc.se)
Wed, 13 Sep 1995 09:38:48 +0200 (DST)

>
> > Robust log file parsers must be prepared to handle receiving duplicate
> > records AND out-of-order records.
Correct.

>
> I should clarify my problem, perhaps. I'm not getting duplicate Stop
> records. I'm getting *different* Stop records. The second Stop record doesn't
> contain the Login-Host entry. Does this better help pinpoint the problem?
I've made a parser for the syslog-entries generated by the Portmaster server
that takes care of this problem, the code is fairly easy to read (appended
at the end of this email). The program itself produces a list of login-
times for each user, another similar program produces a list of usage of
the different ports on a portmaster server, and a third program produces
a compressed listing of how much a specific user has been logged on and how
many times.

Enjoy,

/jp

Ps1. Assumptions: the logs are found in directories with the date as name
(format: YYMMDD), to produce a set of login-entries the "./doit YYMMDD"
must be run first, takes some time, then I always "gzip -v YYMMDD/*" to
save a lot of disk-space (the scripts assume this), then all that I
have to do to watch the accumulated times of user "XXX" is to
"./log-time XXXX" (the output will then be in "XXXX.txt"). Simple really,
and the programs are quite simple too. As in the case of 'pmwho', do
what you like with it.
Ps2. Of course you have to "make" before "./doit YYMMDD" ...
Ps3. Note that many (but not all) of the checks on UNUSED (as in a branch
of 'login', 'connected', ...) are there to handle the out-of-order
records, and YES, they do indeed occur.
Ps4. Haven't more people out there done this already?, if I knew that this
wasn't so I would have posted this long ago.
Ps5. In the script "doit" you should change the line with the text
"for h in portmaster1 portmaster2" into "for h in <insert the names
of your own portmaster servers here>".
Ps6. Carl Rigney: aren't you going to introduce some kind of 'finger'-daemon
into the Portmaster server? it really shouldn't be necessary to login
on the admin account to see who is logged on, naturally some kind of
filtering netmasks for the finger-request may be needed, or a list of
networks/hosts that are allowed this, or something similar.

#!/bin/sh
# This is a shell archive (produced by shar 3.52g2)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 09/13/1995 07:29 UTC by jp@sparc2
# Source directory /home/jp/adm/authlog
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 196 -rw-r--r-- Makefile
# 891 -rwxr-xr-x doit
# 788 -rwxr-xr-x log-time
# 7419 -r--r--r-- portlogin.c
# 2982 -r--r--r-- porttime.c
# 7960 -r--r--r-- portusage.c
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
shar_touch=touch
else
shar_touch=:
echo 'WARNING: not restoring timestamps'
fi
rm -f 1231235999 $$.touch
#
# ============= Makefile ==============
if test -f 'Makefile' && test X"$1" != X"-c"; then
echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
CC=gcc
X
all: portusage portlogin porttime
X
portusage: portusage.c
X $(CC) $@.c $(CFLAGS) -o $@
X
portlogin: portlogin.c
X $(CC) $@.c $(CFLAGS) -o $@
X
porttime: porttime.c
X $(CC) $@.c $(CFLAGS) -o $@
SHAR_EOF
$shar_touch -am 0911185695 'Makefile' &&
chmod 0644 'Makefile' ||
echo 'restore of Makefile failed'
shar_count="`wc -c < 'Makefile'`"
test 196 -eq "$shar_count" ||
echo "Makefile: original size 196, current size $shar_count"
fi
# ============= doit ==============
if test -f 'doit' && test X"$1" != X"-c"; then
echo 'x - skipping doit (File already exists)'
else
echo 'x - extracting doit (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doit' &&
#!/bin/sh
X
if test "x$1" = "x"; then
X echo "usage $0 directory"
X exit 1
fi
X
if test ! -d $1; then
X echo "usage $0 directory"
X exit 1
fi
X
if test ! -f $1/authlog; then
X echo "$0: no such file: $1/authlog"
X exit 1
fi
X
echo "### Start: `date` ###"
echo ""
X
echo "### authlog.log ###"
cat $1/authlog | egrep -v 'portmaster|/dev/ttya: Device busy|/dev/ttya: No such device or address|last message repeated|getpwnam|getpwent' 1>$1/authlog.log
X
for h in portmaster1 portmaster2
do
X echo "### portusage @$h ###"
X cat $1/authlog | ./portusage $h 1>$1/$h-usage.log
X
X echo "### portlogin @$h ###"
X cat $1/authlog | ./portlogin $h 0 1>$1/$h-login0.log
X
X echo "### portlogin 120 @$h ###"
X cat $1/authlog | ./portlogin $h 120 1>$1/$h-login120.log
X
X echo "### portlogin 180 @$h ###"
X cat $1/authlog | ./portlogin $h 180 1>$1/$h-login180.log
done
X
echo ""
echo "### Stop : `date` ###"
X
Xexit 0
SHAR_EOF
$shar_touch -am 0910184895 'doit' &&
chmod 0755 'doit' ||
echo 'restore of doit failed'
shar_count="`wc -c < 'doit'`"
test 891 -eq "$shar_count" ||
echo "doit: original size 891, current size $shar_count"
fi
# ============= log-time ==============
if test -f 'log-time' && test X"$1" != X"-c"; then
echo 'x - skipping log-time (File already exists)'
else
echo 'x - extracting log-time (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'log-time' &&
#!/usr/local/bin/bash
X
# Examples of usage:
# ./log-time 2397 jp Pjp
# ./log-time 8575 anders
# ./log-time 23970
X
if test "x$1" = "x";then
X echo "usage: log-time member# [username] [username2]"
X exit 1
fi
X
/bin/rm -f $1.log $1.txt
X
if test "x$3" != "x"; then
X echo -n "$1/$2/$3: `date` ... "
X gunzip -c 9*/*login0* | egrep "^User $1 |^User m$1 |^User [#%&]$1 |^User [#%&]m$1 |^User $2 |^User [#%&]$2 |^User $3 |^User [#%&]$3 " >$1.log
elif test "x$2" != "x"; then
X echo -n "$1/$2: `date` ... "
X gunzip -c 9*/*login0* | egrep "^User $1 |^User m$1 |^User [#%&]$1 |^User [#%&]m$1 |^User $2 |^User [#%&]$2 " >$1.log
else
X echo -n "$1: `date` ... "
X gunzip -c 9*/*login0* | egrep "^User $1 |^User m$1 |^User [#%&]$1 |^User [#%&]m$1 " >$1.log
fi
X
X./porttime <$1.log >$1.txt
X
date
SHAR_EOF
$shar_touch -am 0911190695 'log-time' &&
chmod 0755 'log-time' ||
echo 'restore of log-time failed'
shar_count="`wc -c < 'log-time'`"
test 788 -eq "$shar_count" ||
echo "log-time: original size 788, current size $shar_count"
fi
# ============= portlogin.c ==============
if test -f 'portlogin.c' && test X"$1" != X"-c"; then
echo 'x - skipping portlogin.c (File already exists)'
else
echo 'x - extracting portlogin.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'portlogin.c' &&
/* portlogin.c */
X
#include <stdio.h>
#include <time.h>
#include <string.h>
X
#define WORDLEN 80
#define PORTS (sizeof(portstatus)/sizeof(portstatus[0]))
#define UNUSED ((time_t)-1)
X
typedef char word[WORDLEN+1];
X
char *prog;
long minutes;
X
struct {
X word portname, dest, username, mon, day, hhmmss;
X time_t tStart;
} portstatus[30];
X
void usage(void)
{
X fprintf(stderr, "usage: %s host minutes < authlog\n", prog);
X exit(1);
}
X
int split(char *p, word *w, int maxcount)
{
X int n = 0;
X char *t, *s = p, ch;
X
X if ((t = strchr(p, '\r')) != NULL) *t = '\0'; /* cut off CR */
X if ((t = strchr(p, '\n')) != NULL) *t = '\0'; /* cut off LF/NL */
X strcat(p, " ");
X
X for(;;) {
X if ((t = strchr(p, ' ')) == NULL) break;
X
X ch = *t;
X *t = '\0';
X strcpy(w[n++], p);
X *t = ch;
X for(p = t+1; *p == ' '; p++) ;
X
X if (n >= maxcount) break;
X }
X
X if ((t = strrchr(s, ' ')) != NULL) *t = '\0';
X return n;
}
X
int getmonth(word w)
{
X static char month[12][4] = {
X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X };
X int n;
X
X for(n = 0; n < sizeof(month)/sizeof(month[0]); n++) {
X if (strcmp(w, month[n]) == 0) return n;
X }
X return -1;
}
X
time_t gettime(word w1, word w2, word w3)
{
X time_t t;
X struct tm tms;
X
X tms.tm_sec = 0;
X tms.tm_min = 0;
X tms.tm_hour = 0;
X tms.tm_mday = 0;
X tms.tm_mon = 0;
X tms.tm_year = 0;
X tms.tm_wday = 0;
X tms.tm_yday = 0;
X tms.tm_isdst = 0;
X
X t = time(0);
X tms = *localtime(&t);
X
X tms.tm_mon = getmonth(w1);
X if ((tms.tm_mon < 0) || (tms.tm_mon > 11)) {
X fprintf(stderr, "bad month: w1=%s\n", w1);
X return -1;
X }
X
X tms.tm_mday = atol(w2);
X if ((tms.tm_mday < 1) || (tms.tm_mday > 31)) {
X fprintf(stderr, "bad mday: w2=%s\n", w2);
X return -1;
X }
X
X if (sscanf(w3, "%ld:%ld:%ld", &tms.tm_hour, &tms.tm_min, &tms.tm_sec) != 3) {
X fprintf(stderr, "bad time: w3=%s\n", w3);
X return -1;
X }
X
X if ((t = mktime(&tms)) == (time_t)-1) {
X fprintf(stderr, "mktime failed: w1=%s, w2=%s, w3=%s\n", w1, w2, w3);
X return -1;
X }
X return t;
}
X
int parse(word *w)
{
X int n, portno = -1;
X time_t t;
X long dif;
X
X if (w == NULL) { /* clean up, display still logged on users */
X for(portno = 0; portno < PORTS; portno++) {
X if (portstatus[portno].tStart != UNUSED) {
X if (minutes == 0) {
X printf("User %-8s: %4ld minutes %-6s [%s %2s %s .. %s %2s %s]\n", portstatus[portno].username, 0, portstatus[portno].dest, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss, "***", "**", "**:**:**");
X }
X portstatus[portno].tStart = UNUSED;
X }
X }
X return 0;
X }
X
X for(n = 0, portno = -1; n < PORTS; n++) {
X if (strcmp(w[6], portstatus[n].portname) == 0) {
X portno = n;
X break;
X }
X }
X if (portno == -1) return 0;
X
X if ((t = gettime(w[0], w[1], w[2])) == (time_t)-1) return 0;
X
X if (strcmp(w[8], "disconnected") == 0) {
X
/*
May 21 12:20:38 portmaster1 dialnet: port S20 session disconnected dest pm1-27
May 21 15:32:28 portmaster1 portmaster: port S9 session disconnected user 2397
*/
X
X if (portstatus[portno].tStart != UNUSED) {
X dif = (long)t - (long)portstatus[portno].tStart;
X if (dif < 0) dif += 365*24*60*60;
X dif = (long)((dif + 59) / 60);
X if (dif >= minutes) {
X printf("User %-8s: %4ld minutes %-6s [%s %2s %s .. %s %2s %s]\n", portstatus[portno].username, dif, portstatus[portno].dest, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss, w[0], w[1], w[2]);
X }
X portstatus[portno].tStart = UNUSED;
X }
X }
X else if (strcmp(w[8], "succeeded") == 0) {
X if (strcmp(w[9], "dest") == 0) {
X if (strcmp(w[7], "connection") == 0) {
X
/*
May 21 12:13:15 portmaster1 dialnet: port S20 connection succeeded dest pm1-27
*/
X strcpy(portstatus[portno].dest, w[10]);
X }
X else if (strcmp(w[10], "Negotiated") != 0) {
X
/*
May 21 12:13:14 portmaster1 dialnet: port S20 #2397 succeeded dest 192.36.170.46
*/
X
X if (portstatus[portno].tStart != UNUSED) {
X if (minutes == 0) {
X printf("User %-8s: %4ld minutes %-6s [%s %2s %s .. %s %2s %s]\n", portstatus[portno].username, 0, portstatus[portno].dest, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss, "***", "**", "**:**:**");
X }
X /* fprintf(stderr, "** Error: port %s user %s [%s %s %s] never logged out\n", portstatus[portno].portname, portstatus[portno].username, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss); */
X portstatus[portno].tStart = UNUSED;
X }
X strcpy(portstatus[portno].username, w[7]);
X strcpy(portstatus[portno].dest, "");
X strcpy(portstatus[portno].mon, w[0]);
X strcpy(portstatus[portno].day, w[1]);
X strcpy(portstatus[portno].hhmmss, w[2]);
X portstatus[portno].tStart = t;
X }
X }
X else if (strcmp(w[7], "Login") == 0) {
X
/*
May 21 15:32:01 portmaster1 portmaster: port S9 Login succeeded for 2397
May 21 15:50:04 portmaster1 portmaster: port S3 Login succeeded for jp
*/
X
X if (portstatus[portno].tStart != UNUSED) {
X if (minutes == 0) {
X printf("User %-8s: %4ld minutes %-6s [%s %2s %s .. %s %2s %s]\n", portstatus[portno].username, 0, portstatus[portno].dest, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss, "***", "**", "**:**:**");
X }
X /* fprintf(stderr, "** Error: port %s user %s [%s %s %s] never logged out\n", portstatus[portno].portname, portstatus[portno].username, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss); */
X portstatus[portno].tStart = UNUSED;
X }
X strcpy(portstatus[portno].username, w[10]);
X strcpy(portstatus[portno].dest, "");
X strcpy(portstatus[portno].mon, w[0]);
X strcpy(portstatus[portno].day, w[1]);
X strcpy(portstatus[portno].hhmmss, w[2]);
X portstatus[portno].tStart = t;
X }
X }
X else {
X return 0;
X }
X return 1;
}
X
/*
May 21 11:36:06 portmaster1 portmaster: port S15 Login succeeded for 2397
May 21 11:36:41 portmaster1 portmaster: port S15 session disconnected user 2397
May 21 12:13:14 portmaster1 dialnet: port S20 #2397 succeeded dest 192.36.170.46
May 21 12:13:15 portmaster1 dialnet: port S20 connection succeeded dest pm1-27
May 21 12:20:38 portmaster1 dialnet: port S20 session disconnected dest pm1-27
May 21 15:32:01 portmaster1 portmaster: port S9 Login succeeded for 2397
May 21 15:32:28 portmaster1 portmaster: port S9 session disconnected user 2397
May 21 15:50:04 portmaster1 portmaster: port S3 Login succeeded for jp
May 21 16:04:28 portmaster1 portmaster: port S3 session disconnected user jp
*/
X
void main(int argc, char *argv[])
{
X char *p, *host;
X char s[BUFSIZ];
X int n, m;
X word line[20];
X
X p = strrchr(argv[0], '/');
X prog = p ? p+1 : argv[0];
X
X if (argc != 3) usage();
X host = argv[1];
X minutes = atol(argv[2]); /* minutes */
X
X memset(&portstatus, '\0', sizeof(portstatus));
X for(n = 0; n < PORTS; n++) {
X portstatus[n].tStart = UNUSED;
X sprintf(portstatus[n].portname, "S%d", n);
X }
X
X while (fgets(s, sizeof(s), stdin)) {
X m = split(s, line, sizeof(line)/sizeof(line[0]));
X if (m >= 4) {
X if (strcmp(line[3], host) != 0) continue;
X }
X if (m < 11) {
#if 0
X fprintf(stderr, "#1# bad line: m=%d [%s]\n", m, s);
#endif
X continue;
X }
X if (!parse(line)) {
#if 0
X fprintf(stderr, "#2# bad line: m=%d [%s]\n", m, s);
#endif
X continue;
X }
X }
X (void)parse(NULL);
X
X exit(0);
}
SHAR_EOF
$shar_touch -am 0910131295 'portlogin.c' &&
chmod 0444 'portlogin.c' ||
echo 'restore of portlogin.c failed'
shar_count="`wc -c < 'portlogin.c'`"
test 7419 -eq "$shar_count" ||
echo "portlogin.c: original size 7419, current size $shar_count"
fi
# ============= porttime.c ==============
if test -f 'porttime.c' && test X"$1" != X"-c"; then
echo 'x - skipping porttime.c (File already exists)'
else
echo 'x - extracting porttime.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'porttime.c' &&
/* porttime.c - calculate used time from Livingston Portmaster logs */
X
#include <stdio.h>
#include <string.h>
X
#define MAX_USER 50
X
struct {
X char name[100];
X int minutes;
X int count;
} user[MAX_USER];
X
char month[4];
X
void parse(char *line)
{
X char *p, name[100];
X int n, minutes, count;
X
X if (line == NULL) { /* show final info */
X if (month[0] != '\0') {
X printf("Month: %s\n", month);
X printf("\tUsername Calls Time (hh:mm)\n");
X printf("\t-------- ----- ------------\n");
X minutes = count = 0;
X for(n = 0; n < MAX_USER; n++) {
X if (user[n].name[0] != '\0') {
X printf("\t%-8s %3d %3d:%02d\n", user[n].name, user[n].count, (int)(user[n].minutes / 60), (user[n].minutes % 60));
X minutes += user[n].minutes;
X count += user[n].count;
X }
X }
X printf("\t-------- ----- ------------\n");
X printf("\t%-8s %3d %3d:%02d\n", "", count, (int)(minutes / 60), (minutes % 60));
X }
X return;
X }
X
X p = strchr(line, '[');
X if (!p) {
X return;
X }
X
X if (strncmp(month, &p[1], 3) != 0) {
X if (month[0] != '\0') {
X printf("Month: %s\n", month);
X printf("\tUsername Calls Time (hh:mm)\n");
X printf("\t-------- ----- ------------\n");
X minutes = count = 0;
X for(n = 0; n < MAX_USER; n++) {
X if (user[n].name[0] != '\0') {
X printf("\t%-8s %3d %3d:%02d\n", user[n].name, user[n].count, (int)(user[n].minutes / 60), (user[n].minutes % 60));
X minutes += user[n].minutes;
X count += user[n].count;
X }
X }
X printf("\t-------- ----- ------------\n");
X printf("\t%-8s %3d %3d:%02d\n", "", count, (int)(minutes / 60), (minutes % 60));
X printf("\n");
X }
X memset(user, '\0', sizeof(user));
X
X month[0] = p[1];
X month[1] = p[2];
X month[2] = p[3];
X month[3] = '\0';
X }
X
X p = strchr(line, ':');
X if (!p) {
X return;
X }
X
X minutes = atoi(&p[1]);
X *p = '\0';
X strcpy(name, &line[5]);
X
X
X for(n = 0; n < MAX_USER; n++) {
X if (strcmp(user[n].name, name) == 0) {
X user[n].minutes += minutes;
X user[n].count++;
X break;
X }
X }
X if (n >= MAX_USER) {
X for(n = 0; n < MAX_USER; n++) {
X if (user[n].name[0] == '\0') {
X strcpy(user[n].name, name);
X user[n].minutes = minutes;
X user[n].count = 1;
X break;
X }
X }
X if (n >= MAX_USER) {
X fprintf(stderr, "** porttime: no room in table for user='%s', time=%d\n", name, minutes);
X }
X }
}
X
/*
User jp : 0 minutes [Sep 9 00:25:45 .. *** ** **:**:**]
User #jp : 2 minutes pm1-22 [Jun 4 13:54:16 .. Jun 4 13:55:37]
User #Pjp : 0 minutes [Aug 22 18:56:18 .. *** ** **:**:**]
User Pjp : 0 minutes [Jul 18 10:17:03 .. *** ** **:**:**]
*/
X
void main(int argc, char *argv[])
{
X char line[BUFSIZ];
X
X memset(user, '\0', sizeof(user));
X memset(month, '\0', sizeof(month));
X
X while (fgets(line, sizeof(line)-1, stdin) != NULL) parse(line);
X
X parse(NULL);
}
X
SHAR_EOF
$shar_touch -am 0911190495 'porttime.c' &&
chmod 0444 'porttime.c' ||
echo 'restore of porttime.c failed'
shar_count="`wc -c < 'porttime.c'`"
test 2982 -eq "$shar_count" ||
echo "porttime.c: original size 2982, current size $shar_count"
fi
# ============= portusage.c ==============
if test -f 'portusage.c' && test X"$1" != X"-c"; then
echo 'x - skipping portusage.c (File already exists)'
else
echo 'x - extracting portusage.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'portusage.c' &&
/* portusage.c */
X
#include <stdio.h>
#include <time.h>
#include <string.h>
X
#define WORDLEN 80
#define PORTS (sizeof(portstatus)/sizeof(portstatus[0]))
#define UNUSED ((time_t)-1)
X
typedef char word[WORDLEN+1];
X
char *prog, *host;
X
struct {
X word portname, dest, username, mon, day, hhmmss;
X time_t tStart, tSum;
} portstatus[30];
X
word lastdate[2];
X
void usage(void)
{
X fprintf(stderr, "usage: %s host < authlog\n", prog);
X exit(1);
}
X
int split(char *p, word *w, int maxcount)
{
X int n = 0;
X char *t, *s = p, ch;
X
X if ((t = strchr(p, '\r')) != NULL) *t = '\0'; /* cut off CR */
X if ((t = strchr(p, '\n')) != NULL) *t = '\0'; /* cut off LF/NL */
X strcat(p, " ");
X
X for(;;) {
X if ((t = strchr(p, ' ')) == NULL) break;
X
X ch = *t;
X *t = '\0';
X strcpy(w[n++], p);
X *t = ch;
X for(p = t+1; *p == ' '; p++) ;
X
X if (n >= maxcount) break;
X }
X
X if ((t = strrchr(s, ' ')) != NULL) *t = '\0';
X return n;
}
X
int getmonth(word w)
{
X static char month[12][4] = {
X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X };
X int n;
X
X for(n = 0; n < sizeof(month)/sizeof(month[0]); n++) {
X if (strcmp(w, month[n]) == 0) return n;
X }
X return -1;
}
X
time_t gettime(word w1, word w2, word w3)
{
X time_t t;
X struct tm tms;
X
X tms.tm_sec = 0;
X tms.tm_min = 0;
X tms.tm_hour = 0;
X tms.tm_mday = 0;
X tms.tm_mon = 0;
X tms.tm_year = 0;
X tms.tm_wday = 0;
X tms.tm_yday = 0;
X tms.tm_isdst = 0;
X
X t = time(0);
X tms = *localtime(&t);
X
X tms.tm_mon = getmonth(w1);
X if ((tms.tm_mon < 0) || (tms.tm_mon > 11)) {
X fprintf(stderr, "bad month: w1=%s\n", w1);
X return -1;
X }
X
X tms.tm_mday = atol(w2);
X if ((tms.tm_mday < 1) || (tms.tm_mday > 31)) {
X fprintf(stderr, "bad mday: w2=%s\n", w2);
X return -1;
X }
X
X if (sscanf(w3, "%ld:%ld:%ld", &tms.tm_hour, &tms.tm_min, &tms.tm_sec) != 3) {
X fprintf(stderr, "bad time: w3=%s\n", w3);
X return -1;
X }
X
X if ((t = mktime(&tms)) == (time_t)-1) {
X fprintf(stderr, "mktime failed: w1=%s, w2=%s, w3=%s\n", w1, w2, w3);
X return -1;
X }
X return t;
}
X
int parse(word *w)
{
X int n, portno = -1;
X time_t t;
X long dif;
X
X if (w == NULL) { /* clean up, display remaining statistics */
X
X time_t t0;
X
X if (lastdate[0][0] != '\0') {
X printf("Statistics (minutes/port/day) from host '%s' on date '%s %2s'\n", host, lastdate[0], lastdate[1]);
X for(n = 0; n < PORTS; n++) {
X dif = (portstatus[n].tSum + 59) / 60;
X printf("%3s:%4ld%s", portstatus[n].portname, dif, (((n + 1) % 8) == 0) ? "\n" : " ");
X portstatus[n].tSum = 0;
X }
X printf("\n\n");
X }
X return 0;
X }
X
X for(n = 0, portno = -1; n < PORTS; n++) {
X if (strcmp(w[6], portstatus[n].portname) == 0) {
X portno = n;
X break;
X }
X }
X if (portno == -1) return 0;
X
X if ((t = gettime(w[0], w[1], w[2])) == (time_t)-1) return 0;
X
X if ((strcmp(w[0], lastdate[0]) != 0) ||
X (strcmp(w[1], lastdate[1]) != 0)) {
X
X /* date change - update and print statistics */
X
X time_t t0;
X
X if (lastdate[0][0] != '\0') {
X printf("Statistics (minutes/port/day) from host '%s' on date '%s %2s'\n", w[3], lastdate[0], lastdate[1]);
X for(n = 0; n < PORTS; n++) {
X if (portstatus[n].tStart != UNUSED) {
X t0 = gettime(portstatus[n].mon, portstatus[n].day, "00:00:00");
X if (t0 == (time_t)-1) continue;
X /* printf("Overlapping: port %3s: %5ld secs [%s %s %s]\n", portstatus[n].portname, t0+86400-portstatus[n].tStart, portstatus[n].mon, portstatus[n].day, portstatus[n].hhmmss); */
X portstatus[n].tSum += t0 + 86400 - portstatus[n].tStart;
X portstatus[n].tStart = t0 + 86400;
X }
X dif = (portstatus[n].tSum + 59) / 60;
X printf("%3s:%4ld%s", portstatus[n].portname, dif, (((n + 1) % 8) == 0) ? "\n" : " ");
X portstatus[n].tSum = 0;
X }
X printf("\n\n");
X }
X strcpy(lastdate[0], w[0]);
X strcpy(lastdate[1], w[1]);
X }
X
X if (strcmp(w[8], "disconnected") == 0) {
X
/*
May 21 12:20:38 portmaster1 dialnet: port S20 session disconnected dest pm1-27
May 21 15:32:28 portmaster1 portmaster: port S9 session disconnected user 2397
*/
X
X if (portstatus[portno].tStart != UNUSED) {
X dif = (long)t - (long)portstatus[portno].tStart;
X if (dif < 0) dif += 365*24*60*60;
X /* printf("Accumulate: port %3s: %5ld + %-5ld [%s %s %s .. %s %s %s]\n", portstatus[portno].portname, portstatus[portno].tSum, dif, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss, w[0], w[1], w[2]); */
X portstatus[portno].tSum += dif;
X portstatus[portno].tStart = UNUSED;
X }
X }
X else if (strcmp(w[8], "succeeded") == 0) {
X if (strcmp(w[9], "dest") == 0) {
X if (strcmp(w[7], "connection") == 0) {
X
/*
May 21 12:13:15 portmaster1 dialnet: port S20 connection succeeded dest pm1-27
*/
X strcpy(portstatus[portno].dest, w[10]);
X }
X else if (strcmp(w[10], "Negotiated") != 0) {
X
/*
May 21 12:13:14 portmaster1 dialnet: port S20 #2397 succeeded dest 192.36.170.46
*/
X
#if 0
X if (portstatus[portno].tStart != UNUSED) {
X fprintf(stderr, "** Error: port %s user %s [%s %s %s] never logged out\n", portstatus[portno].portname, portstatus[portno].username, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss);
X portstatus[portno].tStart = UNUSED;
X }
#endif
X strcpy(portstatus[portno].username, w[7]);
X strcpy(portstatus[portno].dest, "");
X strcpy(portstatus[portno].mon, w[0]);
X strcpy(portstatus[portno].day, w[1]);
X strcpy(portstatus[portno].hhmmss, w[2]);
X portstatus[portno].tStart = t;
X }
X }
X else if (strcmp(w[7], "Login") == 0) {
X
/*
May 21 15:32:01 portmaster1 portmaster: port S9 Login succeeded for 2397
May 21 15:50:04 portmaster1 portmaster: port S3 Login succeeded for jp
*/
X
#if 0
X if (portstatus[portno].tStart != UNUSED) {
X fprintf(stderr, "** Error: port %s user %s [%s %s %s] never logged out\n", portstatus[portno].portname, portstatus[portno].username, portstatus[portno].mon, portstatus[portno].day, portstatus[portno].hhmmss);
X portstatus[portno].tStart = UNUSED;
X }
#endif
X strcpy(portstatus[portno].username, w[10]);
X strcpy(portstatus[portno].dest, "");
X strcpy(portstatus[portno].mon, w[0]);
X strcpy(portstatus[portno].day, w[1]);
X strcpy(portstatus[portno].hhmmss, w[2]);
X portstatus[portno].tStart = t;
X }
X }
X else {
X return 0;
X }
X return 1;
}
X
/*
May 21 11:36:06 portmaster1 portmaster: port S15 Login succeeded for 2397
May 21 11:36:41 portmaster1 portmaster: port S15 session disconnected user 2397
May 21 12:13:14 portmaster1 dialnet: port S20 #2397 succeeded dest 192.36.170.46
May 21 12:13:15 portmaster1 dialnet: port S20 connection succeeded dest pm1-27
May 21 12:20:38 portmaster1 dialnet: port S20 session disconnected dest pm1-27
May 21 15:32:01 portmaster1 portmaster: port S9 Login succeeded for 2397
May 21 15:32:28 portmaster1 portmaster: port S9 session disconnected user 2397
May 21 15:50:04 portmaster1 portmaster: port S3 Login succeeded for jp
May 21 16:04:28 portmaster1 portmaster: port S3 session disconnected user jp
*/
X
void main(int argc, char *argv[])
{
X char *p;
X char s[BUFSIZ];
X int n, m;
X word line[20];
X
X p = strrchr(argv[0], '/');
X prog = p ? p+1 : argv[0];
X
X strcpy(lastdate[0], "");
X strcpy(lastdate[1], "");
X
X if (argc != 2) usage();
X host = argv[1];
X
X memset(&portstatus, '\0', sizeof(portstatus));
X for(n = 0; n < PORTS; n++) {
X portstatus[n].tStart = UNUSED;
X portstatus[n].tSum = 0;
X sprintf(portstatus[n].portname, "S%d", n);
X }
X
X while (fgets(s, sizeof(s), stdin)) {
X m = split(s, line, sizeof(line)/sizeof(line[0]));
X if (m >= 4) {
X if (strcmp(line[3], host) != 0) continue;
X }
X if (m < 11) {
#if 0
X fprintf(stderr, "#1# bad line: m=%d [%s]\n", m, s);
#endif
X continue;
X }
X if (!parse(line)) {
#if 0
X fprintf(stderr, "#2# bad line: m=%d [%s]\n", m, s);
#endif
X continue;
X }
X }
X (void)parse(0);
X
X exit(0);
}
SHAR_EOF
$shar_touch -am 0910181995 'portusage.c' &&
chmod 0444 'portusage.c' ||
echo 'restore of portusage.c failed'
shar_count="`wc -c < 'portusage.c'`"
test 7960 -eq "$shar_count" ||
echo "portusage.c: original size 7960, current size $shar_count"
fi
exit 0