diff -ruN tcpserver.c.orig tcpserver.c
--- tcpserver.c.orig	2000-03-18 10:18:42.000000000 -0500
+++ tcpserver.c	2007-12-22 02:41:24.000000000 -0500
@@ -1,6 +1,14 @@
+#ifdef __dietlibc__
+#define NO_GETLOADAVG
+#endif
+
 #include <sys/types.h>
 #include <sys/param.h>
 #include <netdb.h>
+#include <stdlib.h>
+#ifdef NO_GETLOADAVG
+#include <unistd.h>
+#endif
 #include "uint16.h"
 #include "str.h"
 #include "byte.h"
@@ -28,6 +36,18 @@
 #include "sig.h"
 #include "dns.h"
 
+
+#ifdef SOLARIS
+#include <kstat.h>
+static kstat_ctl_t   *kc;
+#ifndef FSCALE
+#define FSHIFT  8               /* bits to right of fixed binary point */
+#define FSCALE  (1<<FSHIFT)
+#endif /* FSCALE */
+
+#define loaddouble(la) ((double)(la) / FSCALE)
+#endif
+
 int verbosity = 1;
 int flagkillopts = 1;
 int flagdelay = 1;
@@ -59,11 +79,22 @@
 static stralloc tmp;
 static stralloc fqdn;
 static stralloc addresses;
+static stralloc diemsg_buf;
+static stralloc diemsg2_buf;
+static stralloc diemsg3_buf;
+static stralloc diemsg4_buf;
 
 char bspace[16];
 buffer b;
 
 
+typedef struct
+{
+  char ip[4];
+  pid_t pid;
+} baby;
+
+baby *child;
 
 /* ---------------------------- child */
 
@@ -72,6 +103,13 @@
 int flagdeny = 0;
 int flagallownorules = 0;
 char *fnrules = 0;
+unsigned long maxload = 0;
+long maxconnip = -1;
+long maxconnc = -1;
+char *diemsg = "";
+char *diemsg2 = "";
+char *diemsg3 = "";
+char *diemsg4 = "";
 
 void drop_nomem(void)
 {
@@ -110,6 +148,8 @@
   strerr_die4sys(111,DROP,"unable to read ",fnrules,": ");
 }
 
+unsigned long limit = 40;
+
 void found(char *data,unsigned int datalen)
 {
   unsigned int next0;
@@ -125,6 +165,29 @@
 	if (data[1 + split] == '=') {
 	  data[1 + split] = 0;
 	  env(data + 1,data + 1 + split + 1);
+	  if (str_diff(data+1, "MAXLOAD") == 0) scan_ulong(data+1+split+1,&maxload);
+	  if (str_diff(data+1, "MAXCONNIP") == 0) scan_ulong(data+1+split+1,&maxconnip);
+	  if (str_diff(data+1, "MAXCONNC") == 0) scan_ulong(data+1+split+1,&maxconnc);
+	  if (str_diff(data+1, "DIEMSG") == 0) {
+	    if (!stralloc_copys(&diemsg_buf,data+1+split+1)) drop_nomem();
+	    if (!stralloc_0(&diemsg_buf)) drop_nomem();
+	    diemsg = diemsg_buf.s;
+	  }
+	  if (str_diff(data+1, "DIEMSG_MAXLOAD") == 0) {
+	    if (!stralloc_copys(&diemsg2_buf,data+1+split+1)) drop_nomem();
+	    if (!stralloc_0(&diemsg2_buf)) drop_nomem();
+	    diemsg2 = diemsg2_buf.s;
+	  }
+	  if (str_diff(data+1, "DIEMSG_MAXCONNIP") == 0) {
+	    if (!stralloc_copys(&diemsg3_buf,data+1+split+1)) drop_nomem();
+	    if (!stralloc_0(&diemsg3_buf)) drop_nomem();
+	    diemsg3 = diemsg3_buf.s;
+	  }
+	  if (str_diff(data+1, "DIEMSG_MAXCONNC") == 0) {
+	    if (!stralloc_copys(&diemsg4_buf,data+1+split+1)) drop_nomem();
+	    if (!stralloc_0(&diemsg4_buf)) drop_nomem();
+	    diemsg4 = diemsg4_buf.s;
+	  }
 	}
 	break;
     }
@@ -133,9 +196,53 @@
   }
 }
 
+unsigned long getprocla(void)
+{
+#ifdef SOLARIS
+  kstat_t       *ksp;
+  kstat_named_t *knp;
+  double lavg;
+  kstat_chain_update(kc);
+  ksp = kstat_lookup(kc, "unix", 0, "system_misc");
+  kstat_read(kc,ksp,NULL);
+  knp = kstat_data_lookup(ksp,"avenrun_1min");
+  lavg = loaddouble(knp->value.ui32);
+  return (unsigned long)(lavg * 100);
+#else
+#ifdef NO_GETLOADAVG
+  int lret;
+  int i;
+  unsigned long u1, u2;
+  char *s;
+  static stralloc loadavg_data = {0};
+
+  lret = openreadclose("/proc/loadavg", &loadavg_data, 10);
+  if (lret != -1) {
+    /* /proc/loadavg format is:
+     * 13.08 3.04 1.00 34/170 14190 */
+    s = loadavg_data.s;
+    i = scan_ulong (s, &u1); s+=i;
+    if ((i>0) && (i<5) && (*s == '.')) { /* load should be < 10000 */
+      i = scan_ulong (s+1,&u2);
+      if (i==2) { /* we require two decimal places */
+        return (u1 * 100 + u2);
+      }
+      return (u1 * 100);
+    }
+  }
+#else
+  double result;
+  if (getloadavg(&result, 1) == 1) {
+    return (result * 100);
+  }
+#endif
+#endif
+}
+
 void doit(int t)
 {
   int j;
+  unsigned long curload = 0;
 
   remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0;
 
@@ -211,6 +318,26 @@
     }
   }
 
+  if (maxload) {
+    curload = getprocla();
+    if (curload > maxload) flagdeny = 2;
+  }
+  
+  if (!flagdeny && (maxconnip != -1 || maxconnc != -1)) {
+  	unsigned long u;
+  	long c1=0, cc=0;
+  	for (u=0; u < limit; u++) if (child[u].pid != 0) { 
+  		if ((child[u].ip[0] == remoteip[0]) &&
+  		    (child[u].ip[1] == remoteip[1]) &&
+  		    (child[u].ip[2] == remoteip[2]) ) {
+  		    cc++;
+  		    if (child[u].ip[3] == remoteip[3]) c1++;
+  		}
+  	}
+	if (maxconnc != -1 && (cc >= maxconnc)) flagdeny = 4;
+	if (maxconnip != -1 && (c1 >= maxconnip)) flagdeny = 3;
+  }
+
   if (verbosity >= 2) {
     strnum[fmt_ulong(strnum,getpid())] = 0;
     if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem();
@@ -223,11 +350,38 @@
     cats(":"); safecats(remoteipstr);
     cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
     cats(":"); safecats(remoteportstr);
+    if (flagdeny == 2) {
+    	char curloadstr[FMT_ULONG];
+    	curloadstr[fmt_ulong(curloadstr,curload)] = 0;
+    	cats(" "); safecats ("MAXLOAD"); cats(":"); safecats(curloadstr);
+    }
+    if (flagdeny == 3) {
+    	char maxconstr[FMT_ULONG];
+    	maxconstr[fmt_ulong(maxconstr,maxconnip)] = 0;
+    	cats(" "); safecats ("MAXCONNIP"); cats(":"); safecats(maxconstr);
+    }
+    if (flagdeny == 4) {
+    	char maxconstr[FMT_ULONG];
+    	maxconstr[fmt_ulong(maxconstr,maxconnc)] = 0;
+    	cats(" "); safecats ("MAXCONNC"); cats(":"); safecats(maxconstr);
+    }
     cats("\n");
     buffer_putflush(buffer_2,tmp.s,tmp.len);
   }
 
-  if (flagdeny) _exit(100);
+  if (flagdeny) {
+    if ((flagdeny==2) && *diemsg2) diemsg = diemsg2;
+    if ((flagdeny==3) && *diemsg3) diemsg = diemsg3;
+    if ((flagdeny==4) && *diemsg4) diemsg = diemsg4;
+    if (*diemsg) {
+      buffer_init(&b,write,t,bspace,sizeof bspace);
+      buffer_puts(&b,diemsg);
+      if (buffer_putsflush(&b,"\r\n") == -1)
+        strerr_die2sys(111,DROP,"unable to print diemsg: ");
+    }
+    sleep(1);
+    _exit(100);
+  }
 }
 
 
@@ -253,7 +407,6 @@
   _exit(100);
 }
 
-unsigned long limit = 40;
 unsigned long numchildren = 0;
 
 int flag1 = 0;
@@ -278,6 +431,7 @@
 {
   int wstat;
   int pid;
+  unsigned long u;
  
   while ((pid = wait_nohang(&wstat)) > 0) {
     if (verbosity >= 2) {
@@ -286,6 +440,8 @@
       strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);
     }
     if (numchildren) --numchildren; printstatus();
+    for (u=0; u < limit; u++) if (child[u].pid == pid) { child[u].pid = 0; break; }
+    if (u == limit) strerr_die1x(111,"tcpserver: ERROR: dead child not found?!"); /* never happens */
   }
 }
 
@@ -299,6 +455,7 @@
   unsigned long u;
   int s;
   int t;
+  pid_t pid;
  
   while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof)
     switch(opt) {
@@ -332,6 +489,14 @@
   argc -= optind;
   argv += optind;
 
+  x = env_get("MAXLOAD"); if (x) scan_ulong(x,&maxload);
+  x = env_get("MAXCONNIP"); if (x) scan_ulong(x,&maxconnip);
+  x = env_get("MAXCONNC"); if (x) scan_ulong(x,&maxconnc);
+  x = env_get("DIEMSG"); if (x) diemsg = x;
+  x = env_get("DIEMSG_MAXLOAD"); if (x) diemsg2 = x;
+  x = env_get("DIEMSG_MAXCONNIP"); if (x) diemsg3 = x;
+  x = env_get("DIEMSG_MAXCONNC"); if (x) diemsg4 = x;
+  
   if (!verbosity)
     buffer_2->fd = -1;
  
@@ -352,6 +517,10 @@
   }
 
   if (!*argv) usage();
+  
+  child = calloc(sizeof(baby),limit);
+  if (!child)
+    strerr_die2x(111,FATAL,"out of memory for MAXCONNIP tracking");
  
   sig_block(sig_child);
   sig_catch(sig_child,sigchld);
@@ -393,6 +562,9 @@
  
   close(0);
   close(1);
+  #ifdef SOLARIS
+  kc = kstat_open();
+  #endif  
   printstatus();
  
   for (;;) {
@@ -405,7 +577,7 @@
     if (t == -1) continue;
     ++numchildren; printstatus();
  
-    switch(fork()) {
+    switch(pid=fork()) {
       case 0:
         close(s);
         doit(t);
@@ -420,6 +592,10 @@
       case -1:
         strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
         --numchildren; printstatus();
+        break;
+      default:
+        for (u=0; u < limit; u++) if (child[u].pid == 0) { byte_copy(child[u].ip,4,remoteip); child[u].pid = pid; break; }
+	if (u == limit) strerr_die1x(111,"tcpserver: ERROR: no empty space for new child?!"); /* never happens */
     }
     close(t);
   }
