Commit message:
- add humanize_number function and manual
- split trimdomain into seperate file from logwtmp.c
- ANSI-fy logwtmp.c while we're here

(Mostly obtained from: FreeBSD)
Index: Makefile
===================================================================
RCS file: /cvs/src/lib/libutil/Makefile,v
retrieving revision 1.3
diff -u -u -r1.3 Makefile
--- Makefile	22 Sep 2004 05:06:57 -0000	1.3
+++ Makefile	2 Nov 2004 16:20:36 -0000
@@ -10,13 +10,15 @@
 SRCS=	login.c login_tty.c logout.c logwtmp.c pty.c \
 	login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
 	login_crypt.c _secure_path.c uucplock.c property.c auth.c \
-	realhostname.c fparseln.c stub.c pidfile.c
+	realhostname.c fparseln.c stub.c pidfile.c trimdomain.c \
+	humanize_number.c
 INCS=	libutil.h login_cap.h
 
 MAN+=	login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
 	login_cap.3 login_class.3 login_times.3 login_ok.3 \
 	_secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
-	realhostname_sa.3 trimdomain.3 fparseln.3 pidfile.3
+	realhostname_sa.3 trimdomain.3 fparseln.3 pidfile.3 \
+	humanize_number.3
 MAN+=	login.conf.5 auth.conf.5
 MLINKS+= property.3 properties_read.3  property.3 properties_free.3
 MLINKS+= property.3 property_find.3
Index: humanize_number.3
===================================================================
RCS file: humanize_number.3
diff -N humanize_number.3
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ humanize_number.3	2 Nov 2004 15:55:16 -0000
@@ -0,0 +1,149 @@
+.\"	$NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $
+.\" $FreeBSD: /repoman/r/ncvs/src/lib/libutil/humanize_number.3,v 1.4.2.1 2004/09/28 18:24:50 pjd Exp $
+.\" $DragonFly$
+.\"
+.\" Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Luke Mewburn and by Tomas Svensson.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"        This product includes software developed by the NetBSD
+.\"        Foundation, Inc. and its contributors.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\"    contributors may be used to endorse or promote products derived
+.\"    from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd May 25, 2004
+.Dt HUMANIZE_NUMBER 3
+.Os
+.Sh NAME
+.Nm humanize_number
+.Nd format a number into a human readable form
+.Sh LIBRARY
+.Lb libutil
+.Sh SYNOPSIS
+.In libutil.h
+.Ft int
+.Fo humanize_number
+.Fa "char *buf" "size_t len" "int64_t number" "const char *suffix"
+.Fa "int scale" "int flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn humanize_number
+function formats the signed 64-bit quantity given in
+.Fa number
+into
+.Fa buffer .
+A space and then
+.Fa suffix
+is appended to the end.
+The buffer pointed to by
+.Fa buffer
+must be at least
+.Fa len
+bytes bytes long.
+.Pp
+If the formatted number (including
+.Fa suffix )
+would be too long to fit into
+.Fa buffer ,
+then divide
+.Fa number
+by 1024 until it will.
+In this case, prefix
+.Fa suffix
+with the appropriate SI designator.
+.Pp
+The prefixes are:
+.Bl -column "Prefix" "Description" "Multiplier" -offset indent
+.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
+.It Li k Ta No kilo Ta 1024
+.It Li M Ta No mega Ta 1048576
+.It Li G Ta No giga Ta 1073741824
+.It Li T Ta No tera Ta 1099511627776
+.It Li P Ta No peta Ta 1125899906842624
+.It Li E Ta No exa Ta 1152921504606846976
+.El
+.Pp
+The
+.Fa len
+argument must be at least 4 plus the length of
+.Fa suffix ,
+in order to ensure a useful result is generated into
+.Fa buffer .
+To use a specific prefix, specify this as
+.Fa scale
+(multiplier = 1024 ^ scale).
+This cannot be combined with any of the
+.Fa scale
+flags below.
+.Pp
+The following flags may be passed in
+.Fa scale :
+.Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
+.It Dv HN_AUTOSCALE
+Format the buffer using the lowest multiplier possible.
+.It Dv HN_GETSCALE
+Return the prefix index number (the number of times
+.Fa number
+must be divided to fit) instead of formatting it to the buffer.
+.El
+.Pp
+The following flags may be passed in
+.Fa flags :
+.Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
+.It Dv HN_DECIMAL
+If the final result is less than 10, display it using one digit.
+.It Dv HN_NOSPACE
+Do not put a space between
+.Fa number
+and the prefix.
+.It Dv HN_B
+Use
+.Ql B
+(bytes) as prefix if the original result does not have a prefix.
+.It Dv HN_DIVISOR_1000
+Divide
+.Fa number
+with 1000 instead of 1024.
+.El
+.Sh RETURN VALUES
+The
+.Fn humanize_number
+function returns the number of characters stored in
+.Fa buffer
+(excluding the terminating
+.Dv NUL )
+upon success, or \-1 upon failure.
+If
+.Dv HN_GETSCALE
+is specified, the prefix index number will be returned instead.
+.Sh HISTORY
+The
+.Fn humanize_number
+function first appeared in
+.Nx 2.0 .
Index: humanize_number.c
===================================================================
RCS file: humanize_number.c
diff -N humanize_number.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ humanize_number.c	2 Nov 2004 16:32:42 -0000
@@ -0,0 +1,149 @@
+/*	$NetBSD: humanize_number.c,v 1.8 2004/07/27 01:56:24 enami Exp $	*/
+/* $DragonFly$ */
+
+/*
+ * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the NetBSD
+ *      Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: /repoman/r/ncvs/src/lib/libutil/humanize_number.c,v 1.1.2.1 2004/09/28 18:24:10 pjd Exp $
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <libutil.h>
+
+int
+humanize_number(char *buf, size_t len, int64_t bytes,
+    const char *suffix, int scale, int flags)
+{
+	const char *prefixes, *sep;
+	int	b, i, r, maxscale, s1, s2, sign;
+	int64_t	divisor, max;
+	size_t	baselen;
+
+	assert(buf != NULL);
+	assert(suffix != NULL);
+	assert(scale >= 0);
+
+	if (flags & HN_DIVISOR_1000) {
+		/* SI for decimal multiplies */
+		divisor = 1000;
+		if (flags & HN_B)
+			prefixes = "B\0k\0M\0G\0T\0P\0E";
+		else
+			prefixes = "\0\0k\0M\0G\0T\0P\0E";
+	} else {
+		/*
+		 * binary multiplies
+		 * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+		 */
+		divisor = 1024;
+		if (flags & HN_B)
+			prefixes = "B\0K\0M\0G\0T\0P\0E";
+		else
+			prefixes = "\0\0K\0M\0G\0T\0P\0E";
+	}
+
+#define	SCALE2PREFIX(scale)	(&prefixes[(scale) << 1])
+	maxscale = 7;
+
+	if (scale >= maxscale &&
+	    (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
+		return (-1);
+
+	if (buf == NULL || suffix == NULL)
+		return (-1);
+
+	if (len > 0)
+		buf[0] = '\0';
+	if (bytes < 0) {
+		sign = -1;
+		bytes *= -100;
+		baselen = 3;		/* sign, digit, prefix */
+	} else {
+		sign = 1;
+		bytes *= 100;
+		baselen = 2;		/* digit, prefix */
+	}
+	if (flags & HN_NOSPACE)
+		sep = "";
+	else {
+		sep = " ";
+		baselen++;
+	}
+	baselen += strlen(suffix);
+
+	/* Check if enough room for `x y' + suffix + `\0' */
+	if (len < baselen + 1)
+		return (-1);
+
+	if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
+		/* See if there is additional columns can be used. */
+		for (max = 100, i = len - baselen; i-- > 0;)
+			max *= 10;
+
+		for (i = 0; bytes >= max && i < maxscale; i++)
+			bytes /= divisor;
+
+		if (scale & HN_GETSCALE)
+			return (i);
+	} else
+		for (i = 0; i < scale && i < maxscale; i++)
+			bytes /= divisor;
+
+	/* If a value <= 9.9 after rounding and ... */
+	if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
+		/* baselen + \0 + .N */
+		if (len < baselen + 1 + 2)
+			return (-1);
+		b = ((int)bytes + 5) / 10;
+		s1 = b / 10;
+		s2 = b % 10;
+		r = snprintf(buf, len, "%d%s%d%s%s%s",
+		    sign * s1, localeconv()->decimal_point, s2,
+		    sep, SCALE2PREFIX(i), suffix);
+	} else
+		r = snprintf(buf, len, "%lld%s%s%s",
+		    /* LONGLONG */
+		    (long long)(sign * ((bytes + 50) / 100)),
+		    sep, SCALE2PREFIX(i), suffix);
+
+	return (r);
+}
Index: libutil.h
===================================================================
RCS file: /cvs/src/lib/libutil/libutil.h,v
retrieving revision 1.4
diff -u -u -r1.4 libutil.h
--- libutil.h	22 Sep 2004 05:06:57 -0000	1.4
+++ libutil.h	2 Nov 2004 16:14:42 -0000
@@ -58,6 +58,8 @@
 		     struct termios *_termp, struct winsize *_winp);
 int	forkpty (int *_amaster, char *_name,
 		     struct termios *_termp, struct winsize *_winp);
+int	humanize_number(char *_buf, size_t _len, int64_t _number, 
+               const char *_suffix, int _scale, int _flags); 
 const char *uu_lockerr (int _uu_lockresult);
 int	uu_lock (const char *_ttyname);
 int	uu_unlock (const char *_ttyname);
@@ -100,4 +102,12 @@
 #define	FPARSELN_UNESCREST	0x08
 #define	FPARSELN_UNESCALL	0x0f
 
+/* humanize_number(3) */ 
+#define HN_DECIMAL		0x01 
+#define HN_NOSPACE		0x02 
+#define HN_B			0x04 
+#define HN_DIVISOR_1000		0x08 
+#define HN_GETSCALE		0x10 
+#define HN_AUTOSCALE		0x20 
+
 #endif /* !_LIBUTIL_H_ */
Index: logwtmp.c
===================================================================
RCS file: /cvs/src/lib/libutil/logwtmp.c,v
retrieving revision 1.2
diff -u -u -r1.2 logwtmp.c
--- logwtmp.c	17 Jun 2003 04:26:52 -0000	1.2
+++ logwtmp.c	2 Nov 2004 16:42:12 -0000
@@ -32,19 +32,18 @@
  *
  * @(#)logwtmp.c	8.1 (Berkeley) 6/4/93
  * $FreeBSD: src/lib/libutil/logwtmp.c,v 1.14 2000/01/15 03:26:54 shin Exp $
- * $DragonFly: src/lib/libutil/logwtmp.c,v 1.2 2003/06/17 04:26:52 dillon Exp $
+ * $DragonFly$
  */
 
+#include <sys/cdefs.h>
 #include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/types.h>
 #include <sys/file.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 
 #include <libutil.h>
 #include <netdb.h>
+#include <stdio.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
@@ -55,65 +54,9 @@
 #define	NI_WITHSCOPEID	0
 #endif
 
-void
-trimdomain(char *fullhost, int hostsize)
-{
-    static char domain[MAXHOSTNAMELEN];
-    static int first = 1;
-    static size_t dlen;
-    char *s, *end;
-    int spn, ok;
-
-    if (first) {
-        first = 0;
-        if (gethostname(domain, sizeof(domain) - 1) == 0 &&
-            (s = strchr(domain, '.')))
-            memmove(domain, s + 1, strlen(s + 1) + 1);
-        else
-            domain[0] = '\0';
-        dlen = strlen(domain);
-    }
-
-    if (domain[0] != '\0') {
-	s = fullhost;
-        end = s + hostsize + 1;
-	for (; (s = memchr(s, '.', end - s)) != NULL; s++)
-            if (!strncasecmp(s + 1, domain, dlen)) {
-                if (s[dlen + 1] == '\0') {
-               	    *s = '\0';    /* Found - lose the domain */
-                    break;
-                } else if (s[dlen + 1] == ':') {	/* $DISPLAY ? */
-                    ok = dlen + 2;
-                    spn = strspn(s + ok, "0123456789");
-                    if (spn > 0 && ok + spn - dlen <= end - s) {
-                        ok += spn;
-                        if (s[ok] == '\0') {
-                            /* host.domain:nn */
-                            memmove(s, s + dlen + 1, ok - dlen);
-                            break;
-                        } else if (s[ok] == '.') {
-                            ok++;
-                            spn = strspn(s + ok, "0123456789");
-                            if (spn > 0 && s[ok + spn] == '\0' &&
-                                ok + spn - dlen <= end - s) {
-                                /* host.domain:nn.nn */
-                                memmove(s, s + dlen + 1, ok + spn - dlen);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-    }
-}
-
-#include <stdio.h>
 
 void
-logwtmp(line, name, host)
-	const char *line;
-	const char *name;
-	const char *host;
+logwtmp(const char *line, const char *name, const char *host)
 {
 	struct utmp ut;
 	struct stat buf;
Index: trimdomain.c
===================================================================
RCS file: trimdomain.c
diff -N trimdomain.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trimdomain.c	2 Nov 2004 16:31:53 -0000
@@ -0,0 +1,117 @@
+/* $DragonFly$ */
+/*
+ * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
+ *   Based on original work by Atsushi Murai <amurai@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: /repoman/r/ncvs/src/lib/libutil/trimdomain.c,v 1.5 2003/10/18 10:04:16 markm Exp $
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+
+#include <libutil.h>
+#include <string.h>
+#include <unistd.h>
+
+static int	isDISP(const char *);
+
+/*-
+ * Trim the current domain name from fullhost, but only if the result
+ * is less than or equal to hostsize in length.
+ *
+ * This function understands $DISPLAY type fullhosts.
+ *
+ * For example:
+ *
+ *     trimdomain("abcde.my.domain", 5)       ->   "abcde"
+ *     trimdomain("abcde.my.domain", 4)       ->   "abcde.my.domain"
+ *     trimdomain("abcde.my.domain:0.0", 9)   ->   "abcde:0.0"
+ *     trimdomain("abcde.my.domain:0.0", 8)   ->   "abcde.my.domain:0.0"
+ */
+void
+trimdomain(char *fullhost, int hostsize)
+{
+	static size_t dlen;
+	static int first = 1;
+	static char domain[MAXHOSTNAMELEN];
+	char *end, *s;
+	size_t len;
+
+	if (first) {
+		/* XXX: Should we assume that our domain is this persistent ? */
+		first = 0;
+		if (gethostname(domain, sizeof(domain) - 1) == 0 &&
+		    (s = strchr(domain, '.')) != NULL)
+			memmove(domain, s + 1, strlen(s + 1) + 1);
+		else
+			domain[0] = '\0';
+		dlen = strlen(domain);
+	}
+
+	if (domain[0] == '\0')
+		return;
+
+	s = fullhost;
+	end = s + hostsize + 1;
+	for (; (s = memchr(s, '.', (size_t)(end - s))) != NULL; s++) {
+		if (strncasecmp(s + 1, domain, dlen) == 0) {
+			if (s[dlen + 1] == '\0') {
+				/* Found -- lose the domain. */
+				*s = '\0';
+				break;
+			} else if (s[dlen + 1] == ':' &&
+			    isDISP(s + dlen + 2) &&
+			    (len = strlen(s + dlen + 1)) < (size_t)(end - s)) {
+				/* Found -- shuffle the DISPLAY back. */
+				memmove(s, s + dlen + 1, len + 1);
+				break;
+			}
+		}
+	}
+}
+
+/*
+ * Is the given string NN or NN.NN where ``NN'' is an all-numeric string ?
+ */
+static int
+isDISP(const char *disp)
+{
+	size_t w;
+	int res;
+
+	w = strspn(disp, "0123456789");
+	res = 0;
+	if (w > 0) {
+		if (disp[w] == '\0')
+			res = 1;	/* NN */
+		else if (disp[w] == '.') {
+			disp += w + 1;
+			w = strspn(disp, "0123456789");
+			if (w > 0 && disp[w] == '\0')
+				res = 1;	/* NN.NN */
+		}
+	}
+	return (res);
+}
