Adds some more statistical data to the output of the penctl command
"New" commands are cstatus and connstatus
--- pen.c	2008-05-03 09:29:36.000000000 +0200
+++ pen.c-info	2009-01-12 02:41:00.000000000 +0100
@@ -102,6 +102,8 @@
 	int port;
 	struct in_addr addr;
 	int c;			/* connections */
+	unsigned long long totalconns;	/* total connections */
+	unsigned long long hits;	/* total hits */
 	int weight;		/* default 1 */
 	int prio;
 	int maxc;		/* max connections, soft limit */
@@ -139,6 +141,8 @@
 static int loopflag;
 static int exit_enabled = 0;
 
+static time_t starttime = 0; /* when server was started */
+static unsigned long long hits = 0; /* total number of hits including emergs */
 
 static int clients_max = CLIENTS_MAX;
 static int servers_max = SERVERS_MAX;
@@ -728,6 +732,7 @@
 			inet_ntoa(cli), i, ch);
 	}
 	servers[ch].c++;
+	servers[ch].totalconns++;
 
 	return i;
 }
@@ -933,6 +938,10 @@
 		}
 		if (debuglevel > 2) dump(b, rc);
 
+		hits++;
+		servers[serverindex].hits++;
+		clients[conns[i].clt].last = time(NULL); /* really needed? */
+
 		if (logfp) {
 			log_request(logfp, i, b, rc);
 			if (debuglevel > 2) log_request(stderr, i, b, rc);
@@ -1459,6 +1468,24 @@
 	fclose(fp);
 }
 
+static char *BytePowered(unsigned long long bytes)
+{
+    char tmpstr[25];
+    if (bytes > 10240) {
+       char powers[8] = "KMGTPEZY";
+       int bytepower = -1;
+          while (bytes > 10240) {
+               bytes = bytes / 1024;
+               bytepower++;            
+          }
+       sprintf(tmpstr, "%llu%cB", bytes, powers[bytepower]);
+       return strdup(tmpstr);
+    } else {
+       sprintf(tmpstr, "%llub", bytes);
+       return strdup(tmpstr);
+    }
+}
+
 static void do_cmd(char *b, void (*output)(char *, void *), void *op)
 {
 	char *p, *q;
@@ -1677,6 +1704,54 @@
 				servers[n].sx, servers[n].rx);
 			output(b, op);
 		}
+       } else if (!strcmp(p, "cstatus")) {
+               unsigned long long totalconns = 0;
+               char *pbytesx;
+               char *pbyterx;
+               for (n = 0; n < nservers; n++) {
+                       pbytesx = BytePowered(servers[n].sx);
+                       pbyterx = BytePowered(servers[n].rx);
+                       sprintf(b, "%d addr %s port %d status %d conn %d max %d hard %d weight %d prio %d sx %s rx %s tcon %llu hits %llu\n",
+                               n, inet_ntoa(servers[n].addr), servers[n].port, servers[n].status,
+                               servers[n].c, servers[n].maxc, servers[n].hard,
+                               servers[n].weight, servers[n].prio,
+                               pbytesx, pbyterx, servers[n].totalconns, servers[n].hits);
+                       free(pbytesx); free(pbyterx);
+                       totalconns += servers[n].totalconns; // TODO overflow :>
+                       output(b, op);
+               }
+
+               int now = time(NULL);
+               int clients_active = 0;
+               for (n = 0; n < clients_max; n++) {
+			if ( clients[n].last == 0 ) continue; // timesaving here?
+			if ( (now - clients[n].last) <= tracking_time ) clients_active++;
+               }
+               sprintf(b, "Clients last %ds: %d/%d\nConnections active: %d/%d (last: %d)\n", tracking_time, clients_active, clients_max, connections_used, connections_max, connections_last);
+               output(b, op);
+
+               int duration = time(NULL) - starttime, persec = 0;
+               persec = (hits / duration);
+               char nowstr[80];
+               strftime(nowstr, sizeof(nowstr), "%Y-%m-%d %H:%M:%S", localtime(&starttime) );
+               sprintf(b, "Total Hits since start (%s): %llu (^= %d/s) totalconns: %llu\n", nowstr, hits, persec, totalconns);
+               output(b, op);
+       } else if (!strcmp(p, "connstatus")) {
+               time_t now=time(NULL);
+               sprintf(b, "con\tdownfd\tupfd\tpendd\tpendu\tclient\tserver\tclientip\tage\tlastaccess\tcno\tconnects\n");
+               output(b, op);
+               for (n = 0; n < connections_max; n++) {
+                       if (conns[n].downfd == -1) continue;
+                       sprintf(b,"%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t%ld\t%ld\t%d\t%ld\t\n",
+                       n, conns[n].downfd, conns[n].upfd,
+                       conns[n].downn, conns[n].upn,
+                       conns[n].clt, conns[n].index,
+                       inet_ntoa(clients[conns[n].clt].addr), (long)(now-clients[conns[n].clt].last),
+                       clients[conns[n].clt].last, 
+                       clients[conns[n].clt].cno, clients[conns[n].clt].connects
+                       );
+                       output(b, op);
+               }
 	} else if (!strcmp(p, "status")) {
 		p = webfile;
 		webfile = "/tmp/webfile.html";
@@ -2779,6 +2854,8 @@
 		fclose(pidfp);
 	}
 
+	starttime = time(NULL);
+
 #ifdef HAVE_KQUEUE
 	if (use_kqueue) mainloop_kqueue();
 #else
