[Midnightbsd-cvs] src: usr.sbin/sa: Merge and tag

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Mon Nov 24 20:16:25 EST 2008


Log Message:
-----------
Merge and tag

Modified Files:
--------------
    src/usr.sbin/sa:
        Makefile (r1.1.1.1 -> r1.2)
        extern.h (r1.1.1.1 -> r1.2)
        main.c (r1.1.1.1 -> r1.2)
        pathnames.h (r1.1.1.1 -> r1.2)
        pdb.c (r1.1.1.1 -> r1.2)
        sa.8 (r1.1.1.1 -> r1.2)
        usrdb.c (r1.1.1.1 -> r1.2)

Added Files:
-----------
    src/usr.sbin/sa:
        db.c (r1.1)

-------------- next part --------------
Index: extern.h
===================================================================
RCS file: /home/cvs/src/usr.sbin/sa/extern.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.sbin/sa/extern.h -L usr.sbin/sa/extern.h -u -r1.1.1.1 -r1.2
--- usr.sbin/sa/extern.h
+++ usr.sbin/sa/extern.h
@@ -27,7 +27,8 @@
  * (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: src/usr.sbin/sa/extern.h,v 1.5 2002/07/11 22:11:20 alfred Exp $
+ * $MidnightBSD$
+ * $FreeBSD: src/usr.sbin/sa/extern.h,v 1.7 2007/05/22 06:51:38 dds Exp $
  */
 
 #include <sys/types.h>
@@ -36,32 +37,41 @@
 
 /* structures */
 
+/* All times are stored in 1e-6s units. */
+
 struct cmdinfo {
 	char		ci_comm[MAXCOMLEN+2];	/* command name (+ '*') */
-	u_long		ci_uid;			/* user id */
+	uid_t		ci_uid;			/* user id */
 	u_quad_t	ci_calls;		/* number of calls */
-	u_quad_t	ci_etime;		/* elapsed time */
-	u_quad_t	ci_utime;		/* user time */
-	u_quad_t	ci_stime;		/* system time */
-	u_quad_t	ci_mem;			/* memory use */
-	u_quad_t	ci_io;			/* number of disk i/o ops */
+	double		ci_etime;		/* elapsed time */
+	double		ci_utime;		/* user time */
+	double		ci_stime;		/* system time */
+	double		ci_mem;			/* memory use */
+	double		ci_io;			/* number of disk i/o ops */
 	u_int		ci_flags;		/* flags; see below */
 };
 #define	CI_UNPRINTABLE	0x0001			/* unprintable chars in name */
 
 struct userinfo {
-	u_long		ui_uid;			/* user id; for consistency */
+	uid_t		ui_uid;			/* user id; for consistency */
 	u_quad_t	ui_calls;		/* number of invocations */
-	u_quad_t	ui_utime;		/* user time */
-	u_quad_t	ui_stime;		/* system time */
-	u_quad_t	ui_mem;			/* memory use */
-	u_quad_t	ui_io;			/* number of disk i/o ops */
+	double		ui_utime;		/* user time */
+	double		ui_stime;		/* system time */
+	double		ui_mem;			/* memory use */
+	double		ui_io;			/* number of disk i/o ops */
 };
 
 /* typedefs */
 
 typedef	int (*cmpf_t)(const DBT *, const DBT *);
 
+/* external functions in db.c */
+int db_copy_in(DB **mdb, const char *dbname, const char *name,
+    BTREEINFO *bti, int (*v1_to_v2)(DBT *key, DBT *data));
+int db_copy_out(DB *mdb, const char *dbname, const char *name,
+    BTREEINFO *bti);
+void db_destroy(DB *db, const char *uname);
+
 /* external functions in pdb.c */
 int	pacct_init(void);
 void	pacct_destroy(void);
@@ -69,6 +79,9 @@
 int	pacct_update(void);
 void	pacct_print(void);
 
+/* external functions in readrec.c */
+int	readrec_forward(FILE *f, struct acctv2 *av2);
+
 /* external functions in usrdb.c */
 int	usracct_init(void);
 void	usracct_destroy(void);
@@ -82,6 +95,7 @@
 extern int	Kflag, lflag, mflag, qflag, rflag, sflag, tflag, uflag, vflag;
 extern u_quad_t	cutoff;
 extern cmpf_t	sa_cmp;
+extern const char *pdb_file, *usrdb_file;
 
 /* some #defines to help with db's stupidity */
 
Index: usrdb.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/sa/usrdb.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.sbin/sa/usrdb.c -L usr.sbin/sa/usrdb.c -u -r1.1.1.1 -r1.2
--- usr.sbin/sa/usrdb.c
+++ usr.sbin/sa/usrdb.c
@@ -29,7 +29,8 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.sbin/sa/usrdb.c,v 1.14 2005/02/10 12:43:16 delphij Exp $");
+__FBSDID("$FreeBSD: src/usr.sbin/sa/usrdb.c,v 1.16 2007/05/22 06:51:38 dds Exp $");
+__MBSDID("$MidnightBSD$");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -49,74 +50,69 @@
 
 static DB	*usracct_db;
 
+/* Legacy format in AHZV1 units. */
+struct userinfov1 {
+	uid_t		ui_uid;			/* user id; for consistency */
+	u_quad_t	ui_calls;		/* number of invocations */
+	u_quad_t	ui_utime;		/* user time */
+	u_quad_t	ui_stime;		/* system time */
+	u_quad_t	ui_mem;			/* memory use */
+	u_quad_t	ui_io;			/* number of disk i/o ops */
+};
+
+/*
+ * Convert a v1 data record into the current version.
+ * Return 0 if OK, -1 on error, setting errno.
+ */
+static int
+v1_to_v2(DBT *key, DBT *data)
+{
+	struct userinfov1 uiv1;
+	static struct userinfo uiv2;
+	static uid_t uid;
+
+	if (key->size != sizeof(u_long) || data->size != sizeof(uiv1)) {
+		errno = EFTYPE;
+		return (-1);
+	}
+
+	/* Convert key. */
+	key->size = sizeof(uid_t);
+	uid = (uid_t)*(u_long *)(key->data);
+	key->data = &uid;
+
+	/* Convert data. */
+	memcpy(&uiv1, data->data, data->size);
+	memset(&uiv2, 0, sizeof(uiv2));
+	uiv2.ui_uid = uiv1.ui_uid;
+	uiv2.ui_calls = uiv1.ui_calls;
+	uiv2.ui_utime = ((double)uiv1.ui_utime / AHZV1) * 1000000;
+	uiv2.ui_stime = ((double)uiv1.ui_stime / AHZV1) * 1000000;
+	uiv2.ui_mem = uiv1.ui_mem;
+	uiv2.ui_io = uiv1.ui_io;
+	data->size = sizeof(uiv2);
+	data->data = &uiv2;
+
+	return (0);
+}
+
+/* Copy usrdb_file to in-memory usracct_db. */
 int
 usracct_init()
 {
-	DB *saved_usracct_db;
 	BTREEINFO bti;
-	int error;
 
 	bzero(&bti, sizeof bti);
 	bti.compare = uid_compare;
 
-	usracct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, &bti);
-	if (usracct_db == NULL)
-		return (-1);
-
-	error = 0;
-	if (!iflag) {
-		DBT key, data;
-		int serr, nerr;
-
-		saved_usracct_db = dbopen(_PATH_USRACCT, O_RDONLY, 0, DB_BTREE,
-		    &bti);
-		if (saved_usracct_db == NULL) {
-			error = (errno == ENOENT) ? 0 : -1;
-			if (error)
-				warn("retrieving user accounting summary");
-			goto out;
-		}
-
-		serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST);
-		if (serr < 0) {
-			warn("retrieving user accounting summary");
-			error = -1;
-			goto closeout;
-		}
-		while (serr == 0) {
-			nerr = DB_PUT(usracct_db, &key, &data, 0);
-			if (nerr < 0) {
-				warn("initializing user accounting stats");
-				error = -1;
-				break;
-			}
-
-			serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT);
-			if (serr < 0) {
-				warn("retrieving user accounting summary");
-				error = -1;
-				break;
-			}
-		}
-
-closeout:
-		if (DB_CLOSE(saved_usracct_db) < 0) {
-			warn("closing user accounting summary");
-			error = -1;
-		}
-	}
-
-out:
-	if (error != 0)
-		usracct_destroy();
-	return (error);
+	return (db_copy_in(&usracct_db, usrdb_file, "user accounting",
+	    &bti, v1_to_v2));
 }
 
 void
 usracct_destroy()
 {
-	if (DB_CLOSE(usracct_db) < 0)
-		warn("destroying user accounting stats");
+	db_destroy(usracct_db, "user accounting");
 }
 
 int
@@ -124,7 +120,7 @@
 {
 	DBT key, data;
 	struct userinfo newui;
-	u_long uid;
+	uid_t uid;
 	int rv;
 
 	uid = ci->ci_uid;
@@ -133,13 +129,13 @@
 
 	rv = DB_GET(usracct_db, &key, &data, 0);
 	if (rv < 0) {
-		warn("get key %lu from user accounting stats", uid);
+		warn("get key %u from user accounting stats", uid);
 		return (-1);
 	} else if (rv == 0) {	/* it's there; copy whole thing */
 		/* add the old data to the new data */
 		bcopy(data.data, &newui, data.size);
 		if (newui.ui_uid != uid) {
-			warnx("key %lu != expected record number %lu",
+			warnx("key %u != expected record number %u",
 			    newui.ui_uid, uid);
 			warnx("inconsistent user accounting stats");
 			return (-1);
@@ -159,7 +155,7 @@
 	data.size = sizeof newui;
 	rv = DB_PUT(usracct_db, &key, &data, 0);
 	if (rv < 0) {
-		warn("add key %lu to user accounting stats", uid);
+		warn("add key %u to user accounting stats", uid);
 		return (-1);
 	} else if (rv != 0) {
 		warnx("DB_PUT returned 1");
@@ -169,56 +165,17 @@
 	return (0);
 }
 
+/* Copy in-memory usracct_db to usrdb_file. */
 int
 usracct_update()
 {
-	DB *saved_usracct_db;
-	DBT key, data;
 	BTREEINFO bti;
-	int error, serr, nerr;
 
 	bzero(&bti, sizeof bti);
 	bti.compare = uid_compare;
 
-	saved_usracct_db = dbopen(_PATH_USRACCT, O_RDWR|O_CREAT|O_TRUNC, 0644,
-	    DB_BTREE, &bti);
-	if (saved_usracct_db == NULL) {
-		warn("creating user accounting summary");
-		return (-1);
-	}
-
-	error = 0;
-
-	serr = DB_SEQ(usracct_db, &key, &data, R_FIRST);
-	if (serr < 0) {
-		warn("retrieving user accounting stats");
-		error = -1;
-	}
-	while (serr == 0) {
-		nerr = DB_PUT(saved_usracct_db, &key, &data, 0);
-		if (nerr < 0) {
-			warn("saving user accounting summary");
-			error = -1;
-			break;
-		}
-
-		serr = DB_SEQ(usracct_db, &key, &data, R_NEXT);
-		if (serr < 0) {
-			warn("retrieving user accounting stats");
-			error = -1;
-			break;
-		}
-	}
-
-	if (DB_SYNC(saved_usracct_db, 0) < 0) {
-		warn("syncing process accounting summary");
-		error = -1;
-	}
-	if (DB_CLOSE(saved_usracct_db) < 0) {
-		warn("closing process accounting summary");
-		error = -1;
-	}
-	return error;
+	return (db_copy_out(usracct_db, usrdb_file, "user accounting",
+	    &bti));
 }
 
 void
@@ -239,25 +196,24 @@
 		printf("%-*s %9ju ", MAXLOGNAME - 1,
 		    user_from_uid(ui->ui_uid, 0), (uintmax_t)ui->ui_calls);
 
-		t = (double) (ui->ui_utime + ui->ui_stime) /
-		    (double) AHZ;
-		if (t < 0.0001)		/* kill divide by zero */
-			t = 0.0001;
+		t = (ui->ui_utime + ui->ui_stime) / 1000000;
+		if (t < 0.000001)		/* kill divide by zero */
+			t = 0.000001;
 
 		printf("%12.2f%s ", t / 60.0, "cpu");
 
 		/* ui->ui_calls is always != 0 */
 		if (dflag)
-			printf("%12ju%s",
-			    (uintmax_t)(ui->ui_io / ui->ui_calls), "avio");
+			printf("%12.0f%s",
+			    ui->ui_io / ui->ui_calls, "avio");
 		else
-			printf("%12ju%s", (uintmax_t)ui->ui_io, "tio");
+			printf("%12.0f%s", ui->ui_io, "tio");
 
-		/* t is always >= 0.0001; see above */
+		/* t is always >= 0.000001; see above. */
 		if (kflag)
 			printf("%12.0f%s", ui->ui_mem / t, "k");
 		else
-			printf("%12ju%s", (uintmax_t)ui->ui_mem, "k*sec");
+			printf("%12.0f%s", ui->ui_mem, "k*sec");
 
 		printf("\n");
 
@@ -270,7 +226,7 @@
 static int
 uid_compare(const DBT *k1, const DBT *k2)
 {
-	u_long d1, d2;
+	uid_t d1, d2;
 
 	bcopy(k1->data, &d1, sizeof d1);
 	bcopy(k2->data, &d2, sizeof d2);
Index: sa.8
===================================================================
RCS file: /home/cvs/src/usr.sbin/sa/sa.8,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.sbin/sa/sa.8 -L usr.sbin/sa/sa.8 -u -r1.1.1.1 -r1.2
--- usr.sbin/sa/sa.8
+++ usr.sbin/sa/sa.8
@@ -27,9 +27,10 @@
 .\" (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: src/usr.sbin/sa/sa.8,v 1.19 2005/02/13 23:45:53 ru Exp $
+.\" $MidnightBSD$
+.\" $FreeBSD: src/usr.sbin/sa/sa.8,v 1.20 2007/05/18 12:36:10 dds Exp $
 .\"
-.Dd February 25, 1994
+.Dd November 24, 2008
 .Dt SA 8
 .Os
 .Sh NAME
@@ -38,6 +39,8 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl abcdDfijkKlmnqrstu
+.Op Fl P Ar file
+.Op Fl U Ar file
 .Op Fl v Ar cutoff
 .Op Ar
 .Sh DESCRIPTION
@@ -143,6 +146,12 @@
 Print per-user statistics rather than per-command statistics.
 .It Fl n
 Sort by number of calls.
+.It Fl P Ar file
+Use the specified
+.Ar file
+for accessing the per-command accounting summary database,
+instead of the default
+.Pa /var/account/savacct .
 .It Fl q
 Create no output other than error messages.
 .It Fl r
@@ -155,6 +164,12 @@
 of user and system cpu times.
 If the cpu time is too small to report, ``*ignore*'' appears in
 this field.
+.It Fl U Ar file
+Use the specified
+.Ar file
+for accessing the per-user accounting summary database,
+instead of the default
+.Pa /var/account/usracct .
 .It Fl u
 Superseding all other flags, for each entry
 in the accounting file, print the user ID, total seconds of cpu usage,
Index: pdb.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/sa/pdb.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.sbin/sa/pdb.c -L usr.sbin/sa/pdb.c -u -r1.1.1.1 -r1.2
--- usr.sbin/sa/pdb.c
+++ usr.sbin/sa/pdb.c
@@ -29,13 +29,15 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.sbin/sa/pdb.c,v 1.11 2005/02/10 12:43:16 delphij Exp $");
+__FBSDID("$FreeBSD: src/usr.sbin/sa/pdb.c,v 1.14 2007/05/22 06:51:38 dds Exp $");
+__MBSDID("$MidnightBSD$");
 
 #include <sys/types.h>
 #include <sys/acct.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -48,68 +50,61 @@
 
 static DB	*pacct_db;
 
-int
-pacct_init()
+/* Legacy format in AHZV1 units. */
+struct cmdinfov1 {
+	char		ci_comm[MAXCOMLEN+2];	/* command name (+ '*') */
+	uid_t		ci_uid;			/* user id */
+	u_quad_t	ci_calls;		/* number of calls */
+	u_quad_t	ci_etime;		/* elapsed time */
+	u_quad_t	ci_utime;		/* user time */
+	u_quad_t	ci_stime;		/* system time */
+	u_quad_t	ci_mem;			/* memory use */
+	u_quad_t	ci_io;			/* number of disk i/o ops */
+	u_int		ci_flags;		/* flags; see below */
+};
+
+/*
+ * Convert a v1 data record into the current version.
+ * Return 0 if OK, -1 on error, setting errno.
+ */
+static int
+v1_to_v2(DBT *key __unused, DBT *data)
 {
-	DB *saved_pacct_db;
-	int error;
+	struct cmdinfov1 civ1;
+	static struct cmdinfo civ2;
 
-	pacct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL);
-	if (pacct_db == NULL)
+	if (data->size != sizeof(civ1)) {
+		errno = EFTYPE;
 		return (-1);
-
-	error = 0;
-	if (!iflag) {
-		DBT key, data;
-		int serr, nerr;
-
-		saved_pacct_db = dbopen(_PATH_SAVACCT, O_RDONLY, 0, DB_BTREE,
-		    NULL);
-		if (saved_pacct_db == NULL) {
-			error = errno == ENOENT ? 0 : -1;
-			if (error)
-				warn("retrieving process accounting summary");
-			goto out;
-		}
-
-		serr = DB_SEQ(saved_pacct_db, &key, &data, R_FIRST);
-		if (serr < 0) {
-			warn("retrieving process accounting summary");
-			error = -1;
-			goto closeout;
-		}
-		while (serr == 0) {
-			nerr = DB_PUT(pacct_db, &key, &data, 0);
-			if (nerr < 0) {
-				warn("initializing process accounting stats");
-				error = -1;
-				break;
-			}
-
-			serr = DB_SEQ(saved_pacct_db, &key, &data, R_NEXT);
-			if (serr < 0) {
-				warn("retrieving process accounting summary");
-				error = -1;
-				break;
-			}
-		}
-
-closeout:	if (DB_CLOSE(saved_pacct_db) < 0) {
-			warn("closing process accounting summary");
-			error = -1;
-		}
 	}
+	memcpy(&civ1, data->data, data->size);
+	memset(&civ2, 0, sizeof(civ2));
+	memcpy(civ2.ci_comm, civ1.ci_comm, sizeof(civ2.ci_comm));
+	civ2.ci_uid = civ1.ci_uid;
+	civ2.ci_calls = civ1.ci_calls;
+	civ2.ci_etime = ((double)civ1.ci_etime / AHZV1) * 1000000;
+	civ2.ci_utime = ((double)civ1.ci_utime / AHZV1) * 1000000;
+	civ2.ci_stime = ((double)civ1.ci_stime / AHZV1) * 1000000;
+	civ2.ci_mem = civ1.ci_mem;
+	civ2.ci_io = civ1.ci_io;
+	civ2.ci_flags = civ1.ci_flags;
+	data->size = sizeof(civ2);
+	data->data = &civ2;
+	return (0);
+}
 
-out:	if (error != 0)
-		pacct_destroy();
-	return (error);
+/* Copy pdb_file to in-memory pacct_db. */
+int
+pacct_init()
+{
+	return (db_copy_in(&pacct_db, pdb_file, "process accounting",
+	    NULL, v1_to_v2));
 }
 
 void
 pacct_destroy()
 {
-	if (DB_CLOSE(pacct_db) < 0)
-		warn("destroying process accounting stats");
+	db_destroy(pacct_db, "process accounting");
 }
 
 int
@@ -154,52 +149,12 @@
 	return (0);
 }
 
+/* Copy in-memory pacct_db to pdb_file. */
 int
 pacct_update()
 {
-	DB *saved_pacct_db;
-	DBT key, data;
-	int error, serr, nerr;
-
-	saved_pacct_db = dbopen(_PATH_SAVACCT, O_RDWR|O_CREAT|O_TRUNC, 0644,
-	    DB_BTREE, NULL);
-	if (saved_pacct_db == NULL) {
-		warn("creating process accounting summary");
-		return (-1);
-	}
-
-	error = 0;
-
-	serr = DB_SEQ(pacct_db, &key, &data, R_FIRST);
-	if (serr < 0) {
-		warn("retrieving process accounting stats");
-		error = -1;
-	}
-	while (serr == 0) {
-		nerr = DB_PUT(saved_pacct_db, &key, &data, 0);
-		if (nerr < 0) {
-			warn("saving process accounting summary");
-			error = -1;
-			break;
-		}
-
-		serr = DB_SEQ(pacct_db, &key, &data, R_NEXT);
-		if (serr < 0) {
-			warn("retrieving process accounting stats");
-			error = -1;
-			break;
-		}
-	}
-
-	if (DB_SYNC(saved_pacct_db, 0) < 0) {
-		warn("syncing process accounting summary");
-		error = -1;
-	}
-	if (DB_CLOSE(saved_pacct_db) < 0) {
-		warn("closing process accounting summary");
-		error = -1;
-	}
-	return error;
+	return (db_copy_out(pacct_db, pdb_file, "process accounting",
+	    NULL));
 }
 
 void
@@ -330,7 +285,7 @@
 	int uflow;
 
 	c = cip->ci_calls ? cip->ci_calls : 1;
-	t = (cip->ci_utime + cip->ci_stime) / (double) AHZ;
+	t = (cip->ci_utime + cip->ci_stime) / 1000000;
 	if (t < 0.01) {
 		t = 0.01;
 		uflow = 1;
@@ -340,55 +295,58 @@
 	printf("%8ju ", (uintmax_t)cip->ci_calls);
 	if (cflag) {
 		if (cip != totalcip)
-			printf(" %4.2f%%  ",
-			    cip->ci_calls / (double) totalcip->ci_calls);
+			printf(" %4.1f%%  ", cip->ci_calls /
+			    (double)totalcip->ci_calls * 100);
 		else
 			printf(" %4s   ", "");
 	}
 
 	if (jflag)
-		printf("%11.2fre ", cip->ci_etime / (double) (AHZ * c));
+		printf("%11.3fre ", cip->ci_etime / (1000000 * c));
 	else
-		printf("%11.2fre ", cip->ci_etime / (60.0 * AHZ));
+		printf("%11.3fre ", cip->ci_etime / (60.0 * 1000000));
 	if (cflag) {
 		if (cip != totalcip)
-			printf(" %4.2f%%  ",
-			    cip->ci_etime / (double) totalcip->ci_etime);
+			printf(" %4.1f%%  ", cip->ci_etime /
+			    totalcip->ci_etime * 100);
 		else
 			printf(" %4s   ", "");
 	}
 
 	if (!lflag) {
 		if (jflag)
-			printf("%11.2fcp ", t / (double) cip->ci_calls);
+			printf("%11.3fcp ", t / (double) cip->ci_calls);
 		else
 			printf("%11.2fcp ", t / 60.0);
 		if (cflag) {
 			if (cip != totalcip)
-				printf(" %4.2f%%  ",
-				    (cip->ci_utime + cip->ci_stime) / (double)
-				    (totalcip->ci_utime + totalcip->ci_stime));
+				printf(" %4.1f%%  ",
+				    (cip->ci_utime + cip->ci_stime) /
+				    (totalcip->ci_utime + totalcip->ci_stime) *
+				    100);
 			else
 				printf(" %4s   ", "");
 		}
 	} else {
 		if (jflag)
-			printf("%11.2fu ", cip->ci_utime / (double) (AHZ * c));
+			printf("%11.3fu ", cip->ci_utime / (1000000 * c));
 		else
-			printf("%11.2fu ", cip->ci_utime / (60.0 * AHZ));
+			printf("%11.2fu ", cip->ci_utime / (60.0 * 1000000));
 		if (cflag) {
 			if (cip != totalcip)
-				printf(" %4.2f%%  ", cip->ci_utime / (double) totalcip->ci_utime);
+				printf(" %4.1f%%  ", cip->ci_utime /
+				    (double)totalcip->ci_utime * 100);
 			else
 				printf(" %4s   ", "");
 		}
 		if (jflag)
-			printf("%11.2fs ", cip->ci_stime / (double) (AHZ * c));
+			printf("%11.3fs ", cip->ci_stime / (1000000 * c));
 		else
-			printf("%11.2fs ", cip->ci_stime / (60.0 * AHZ));
+			printf("%11.2fs ", cip->ci_stime / (60.0 * 1000000));
 		if (cflag) {
 			if (cip != totalcip)
-				printf(" %4.2f%%  ", cip->ci_stime / (double) totalcip->ci_stime);
+				printf(" %4.1f%%  ", cip->ci_stime /
+				    (double)totalcip->ci_stime * 100);
 			else
 				printf(" %4s   ", "");
 		}
@@ -398,18 +356,18 @@
 		if (!uflow)
 			printf("%8.2fre/cp ",
 			    cip->ci_etime /
-			    (double) (cip->ci_utime + cip->ci_stime));
+			    (cip->ci_utime + cip->ci_stime));
 		else
 			printf("*ignore*      ");
 	}
 
 	if (Dflag)
-		printf("%10jutio ", (uintmax_t)cip->ci_io);
+		printf("%10.0fio ", cip->ci_io);
 	else
 		printf("%8.0favio ", cip->ci_io / c);
 
 	if (Kflag)
-		printf("%10juk*sec ", (uintmax_t)cip->ci_mem);
+		printf("%10.0fk*sec ", cip->ci_mem);
 	else
 		printf("%8.0fk ", cip->ci_mem / t);
 
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.sbin/sa/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.sbin/sa/Makefile -L usr.sbin/sa/Makefile -u -r1.1.1.1 -r1.2
--- usr.sbin/sa/Makefile
+++ usr.sbin/sa/Makefile
@@ -1,8 +1,11 @@
-# $FreeBSD: src/usr.sbin/sa/Makefile,v 1.10 2005/02/10 07:07:32 delphij Exp $
+# $MidnightBSD$
+# $FreeBSD: src/usr.sbin/sa/Makefile,v 1.12 2007/05/22 10:49:42 dds Exp $
+
+.PATH: ${.CURDIR}/../../usr.bin/lastcomm
 
 PROG=	sa
 MAN=	sa.8
-SRCS=	main.c pdb.c usrdb.c
+SRCS=	main.c db.c pdb.c usrdb.c readrec.c
 
 WARNS?=	6
 
Index: pathnames.h
===================================================================
RCS file: /home/cvs/src/usr.sbin/sa/pathnames.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.sbin/sa/pathnames.h -L usr.sbin/sa/pathnames.h -u -r1.1.1.1 -r1.2
--- usr.sbin/sa/pathnames.h
+++ usr.sbin/sa/pathnames.h
@@ -27,6 +27,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
+ * $MidnightBSD$
  * $FreeBSD: src/usr.sbin/sa/pathnames.h,v 1.4 1999/08/28 01:19:52 peter Exp $
  */
 
Index: main.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/sa/main.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L usr.sbin/sa/main.c -L usr.sbin/sa/main.c -u -r1.1.1.1 -r1.2
--- usr.sbin/sa/main.c
+++ usr.sbin/sa/main.c
@@ -36,7 +36,8 @@
 #endif
 #endif
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.sbin/sa/main.c,v 1.16 2005/02/10 12:43:16 delphij Exp $");
+__FBSDID("$FreeBSD: src/usr.sbin/sa/main.c,v 1.18 2007/05/22 06:51:38 dds Exp $");
+__MBSDID("$MidnightBSD$");
 
 /*
  * sa:	system accounting
@@ -46,6 +47,7 @@
 #include <sys/acct.h>
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <stdint.h>
@@ -56,21 +58,22 @@
 #include "extern.h"
 #include "pathnames.h"
 
-static int	acct_load(const char *, int);
-static u_quad_t	decode_comp_t(comp_t);
-static int	cmp_comm(const char *, const char *);
-static int	cmp_usrsys(const DBT *, const DBT *);
-static int	cmp_avgusrsys(const DBT *, const DBT *);
-static int	cmp_dkio(const DBT *, const DBT *);
-static int	cmp_avgdkio(const DBT *, const DBT *);
-static int	cmp_cpumem(const DBT *, const DBT *);
-static int	cmp_avgcpumem(const DBT *, const DBT *);
-static int	cmp_calls(const DBT *, const DBT *);
-static void	usage(void);
+static FILE	*acct_load(const char *, int);
+static int	 cmp_comm(const char *, const char *);
+static int	 cmp_usrsys(const DBT *, const DBT *);
+static int	 cmp_avgusrsys(const DBT *, const DBT *);
+static int	 cmp_dkio(const DBT *, const DBT *);
+static int	 cmp_avgdkio(const DBT *, const DBT *);
+static int	 cmp_cpumem(const DBT *, const DBT *);
+static int	 cmp_avgcpumem(const DBT *, const DBT *);
+static int	 cmp_calls(const DBT *, const DBT *);
+static void	 usage(void);
 
 int aflag, bflag, cflag, dflag, Dflag, fflag, iflag, jflag, kflag;
 int Kflag, lflag, mflag, qflag, rflag, sflag, tflag, uflag, vflag;
 u_quad_t cutoff = 1;
+const char *pdb_file = _PATH_SAVACCT;
+const char *usrdb_file = _PATH_USRACCT;
 
 static char	*dfltargv[] = { NULL };
 static int	dfltargc = (sizeof dfltargv/sizeof(char *));
@@ -81,12 +84,13 @@
 int
 main(int argc, char **argv)
 {
+	FILE *f;
 	char pathacct[] = _PATH_ACCT;
 	int ch, error = 0;
 
 	dfltargv[0] = pathacct;
 
-	while ((ch = getopt(argc, argv, "abcdDfijkKlmnqrstuv:")) != -1)
+	while ((ch = getopt(argc, argv, "abcdDfijkKlmnP:qrstuU:v:")) != -1)
 		switch (ch) {
 			case 'a':
 				/* print all commands */
@@ -145,6 +149,10 @@
 				/* sort by number of calls */
 				sa_cmp = cmp_calls;
 				break;
+			case 'P':
+				/* specify program database summary file */
+				pdb_file = optarg;
+				break;
 			case 'q':
 				/* quiet; error messages only */
 				qflag = 1;
@@ -165,6 +173,10 @@
 				/* first, print uid and command name */
 				uflag = 1;
 				break;
+			case 'U':
+				/* specify user database summary file */
+				usrdb_file = optarg;
+				break;
 			case 'v':
 				/* cull junk */
 				vflag = 1;
@@ -200,14 +212,12 @@
 
 	/* for each file specified */
 	for (; argc > 0; argc--, argv++) {
-		int	fd;
-
 		/*
 		 * load the accounting data from the file.
 		 * if it fails, go on to the next file.
 		 */
-		fd = acct_load(argv[0], sflag);
-		if (fd < 0)
+		f = acct_load(argv[0], sflag);
+		if (f == NULL)
 			continue;
 
 		if (!uflag && sflag) {
@@ -238,7 +248,7 @@
 			 * the saved stats; better to underbill than overbill,
 			 * but we want every accounting record intact.
 			 */
-			if (ftruncate(fd, 0) == -1) {
+			if (ftruncate(fileno(f), 0) == -1) {
 				warn("couldn't truncate %s", *argv);
 				error = 1;
 			}
@@ -265,8 +275,8 @@
 		/*
 		 * close the opened accounting file
 		 */
-		if (close(fd) == -1) {
-			warn("close %s", *argv);
+		if (fclose(f) == EOF) {
+			warn("fclose %s", *argv);
 			error = 1;
 		}
 	}
@@ -294,25 +304,26 @@
 usage()
 {
 	(void)fprintf(stderr,
-		"usage: sa [-abcdDfijkKlmnqrstu] [-v cutoff] [file ...]\n");
+		"usage: sa [-abcdDfijkKlmnqrstu] [-P file] [-U file] [-v cutoff] [file ...]\n");
 	exit(1);
 }
 
-static int
+static FILE *
 acct_load(const char *pn, int wr)
 {
-	struct acct ac;
+	struct acctv2 ac;
 	struct cmdinfo ci;
 	ssize_t rv;
-	int fd, i;
+	FILE *f;
+	int i;
 
 	/*
 	 * open the file
 	 */
-	fd = open(pn, wr ? O_RDWR : O_RDONLY, 0);
-	if (fd == -1) {
+	f = fopen(pn, wr ? "r+" : "r");
+	if (f == NULL) {
 		warn("open %s %s", pn, wr ? "for read/write" : "read-only");
-		return (-1);
+		return (NULL);
 	}
 
 	/*
@@ -321,13 +332,12 @@
 	 */
 	while (1) {
 		/* get one accounting entry and punt if there's an error */
-		rv = read(fd, &ac, sizeof(struct acct));
-		if (rv == -1)
-			warn("error reading %s", pn);
-		else if (rv > 0 && rv < (int)sizeof(struct acct))
-			warnx("short read of accounting data in %s", pn);
-		if (rv != sizeof(struct acct))
+		rv = readrec_forward(f, &ac);
+		if (rv != 1) {
+			if (rv == EOF)
+				warn("error reading %s", pn);
 			break;
+		}
 
 		/* decode it */
 		ci.ci_calls = 1;
@@ -341,15 +351,15 @@
 			} else
 				ci.ci_comm[i] = c;
 		}
-		if (ac.ac_flag & AFORK)
+		if (ac.ac_flagx & AFORK)
 			ci.ci_comm[i++] = '*';
 		ci.ci_comm[i++] = '\0';
-		ci.ci_etime = decode_comp_t(ac.ac_etime);
-		ci.ci_utime = decode_comp_t(ac.ac_utime);
-		ci.ci_stime = decode_comp_t(ac.ac_stime);
+		ci.ci_etime = ac.ac_etime;
+		ci.ci_utime = ac.ac_utime;
+		ci.ci_stime = ac.ac_stime;
 		ci.ci_uid = ac.ac_uid;
 		ci.ci_mem = ac.ac_mem;
-		ci.ci_io = decode_comp_t(ac.ac_io) / AHZ;
+		ci.ci_io = ac.ac_io;
 
 		if (!uflag) {
 			/* and enter it into the usracct and pacct databases */
@@ -358,34 +368,15 @@
 			if (sflag || (mflag && !qflag))
 				usracct_add(&ci);
 		} else if (!qflag)
-			printf("%6lu %12.2f cpu %12juk mem %12ju io %s\n",
+			printf("%6u %12.3lf cpu %12.0lfk mem %12.0lf io %s\n",
 			    ci.ci_uid,
-			    (ci.ci_utime + ci.ci_stime) / (double) AHZ,
-			    (uintmax_t)ci.ci_mem, (uintmax_t)ci.ci_io,
+			    (ci.ci_utime + ci.ci_stime) / 1000000,
+			    ci.ci_mem, ci.ci_io,
 			    ci.ci_comm);
 	}
 
-	/* finally, return the file descriptor for possible truncation */
-	return (fd);
-}
-
-static u_quad_t
-decode_comp_t(comp_t comp)
-{
-	u_quad_t rv;
-
-	/*
-	 * for more info on the comp_t format, see:
-	 *	/usr/src/sys/kern/kern_acct.c
-	 *	/usr/src/sys/sys/acct.h
-	 *	/usr/src/usr.bin/lastcomm/lastcomm.c
-	 */
-	rv = comp & 0x1fff;	/* 13 bit fraction */
-	comp >>= 13;		/* 3 bit base-8 exponent */
-	while (comp--)
-		rv <<= 3;
-
-	return (rv);
+	/* Finally, return the file stream for possible truncation. */
+	return (f);
 }
 
 /* sort commands, doing the right thing in terms of reversals */
@@ -405,7 +396,7 @@
 cmp_usrsys(const DBT *d1, const DBT *d2)
 {
 	struct cmdinfo c1, c2;
-	u_quad_t t1, t2;
+	double t1, t2;
 
 	memcpy(&c1, d1->data, sizeof(c1));
 	memcpy(&c2, d2->data, sizeof(c2));
@@ -472,8 +463,8 @@
 	memcpy(&c1, d1->data, sizeof(c1));
 	memcpy(&c2, d2->data, sizeof(c2));
 
-	n1 = (double) c1.ci_io / (double) (c1.ci_calls ? c1.ci_calls : 1);
-	n2 = (double) c2.ci_io / (double) (c2.ci_calls ? c2.ci_calls : 1);
+	n1 = c1.ci_io / (double) (c1.ci_calls ? c1.ci_calls : 1);
+	n2 = c2.ci_io / (double) (c2.ci_calls ? c2.ci_calls : 1);
 
 	if (n1 < n2)
 		return -1;
@@ -505,7 +496,7 @@
 cmp_avgcpumem(const DBT *d1, const DBT *d2)
 {
 	struct cmdinfo c1, c2;
-	u_quad_t t1, t2;
+	double t1, t2;
 	double n1, n2;
 
 	memcpy(&c1, d1->data, sizeof(c1));
@@ -514,8 +505,8 @@
 	t1 = c1.ci_utime + c1.ci_stime;
 	t2 = c2.ci_utime + c2.ci_stime;
 
-	n1 = (double) c1.ci_mem / (double) (t1 ? t1 : 1);
-	n2 = (double) c2.ci_mem / (double) (t2 ? t2 : 1);
+	n1 = c1.ci_mem / (t1 ? t1 : 1);
+	n2 = c2.ci_mem / (t2 ? t2 : 1);
 
 	if (n1 < n2)
 		return -1;
--- /dev/null
+++ usr.sbin/sa/db.c
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 2007 Diomidis Spinellis
+ * 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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/sa/db.c,v 1.1 2007/05/22 06:51:38 dds Exp $");
+__MBSDID("$MidnightBSD: src/usr.sbin/sa/db.c,v 1.1 2008/11/25 01:16:24 laffer1 Exp $");
+
+#include <sys/types.h>
+#include <sys/acct.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <db.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "extern.h"
+
+/* Key used to store the version of the database data elements. */
+#define VERSION_KEY "\0VERSION"
+
+/*
+ * Create the in-memory database, *mdb.
+ * If iflag is not set, fill-in mdb with the records of the disk-based
+ * database dbname.
+ * Upgrade old-version records by calling v1_to_v2.
+ * Return 0 if OK, -1 on error.
+ */
+int
+db_copy_in(DB **mdb, const char *dbname, const char *uname, BTREEINFO *bti,
+    int (*v1_to_v2)(DBT *key, DBT *data))
+{
+	DBT key, data;
+	DB *ddb;
+	int error, rv, version;
+
+	if ((*mdb = dbopen(NULL, O_RDWR, 0, DB_BTREE, bti)) == NULL)
+		return (-1);
+
+	if (iflag)
+		return (0);
+
+	if ((ddb = dbopen(dbname, O_RDONLY, 0, DB_BTREE, NULL)) == NULL) {
+		if (errno == ENOENT)
+			return (0);
+		warn("retrieving %s summary", uname);
+		db_destroy(*mdb, uname);
+		return (-1);
+	}
+
+	error = 0;
+
+	/* Obtain/set version. */
+	version = 1;
+	key.data = &VERSION_KEY;
+	key.size = sizeof(VERSION_KEY);
+
+	rv = DB_GET(ddb, &key, &data, 0);
+	if (rv < 0) {
+		warn("get version key from %s stats", uname);
+		error = -1;
+		goto closeout;
+	} else if (rv == 0) {	/* It's there; verify version. */
+		if (data.size != sizeof(version)) {
+			warnx("invalid version size %d in %s",
+			    data.size, uname);
+			error = -1;
+			goto closeout;
+		}
+		memcpy(&version, data.data, data.size);
+		if (version != 2) {
+			warnx("unsupported version %d in %s",
+			    version, uname);
+			error = -1;
+			goto closeout;
+		}
+	}
+
+	for (rv = DB_SEQ(ddb, &key, &data, R_FIRST); rv == 0;
+	    rv = DB_SEQ(ddb, &key, &data, R_NEXT)) {
+
+		/* See if this is a version record. */
+		if (key.size == sizeof(VERSION_KEY) &&
+		    memcmp(key.data, VERSION_KEY, sizeof(VERSION_KEY)) == 0)
+			continue;
+
+		/* Convert record from v1, if needed. */
+		if (version == 1 && v1_to_v2(&key, &data) < 0) {
+			warn("converting %s stats", uname);
+			error = -1;
+			goto closeout;
+		}
+
+		/* Copy record to the in-memory database. */
+		if ((rv = DB_PUT(*mdb, &key, &data, 0)) < 0) {
+			warn("initializing %s stats", uname);
+			error = -1;
+			goto closeout;
+		}
+	}
+	if (rv < 0) {
+		warn("retrieving %s summary", uname);
+		error = -1;
+	}
+
+closeout:
+	if (DB_CLOSE(ddb) < 0) {
+		warn("closing %s summary", uname);
+		error = -1;
+	}
+
+	if (error)
+		db_destroy(*mdb, uname);
+	return (error);
+}
+
+/*
+ * Save the in-memory database mdb to the disk database dbname.
+ * Return 0 if OK, -1 on error.
+ */
+int
+db_copy_out(DB *mdb, const char *dbname, const char *uname, BTREEINFO *bti)
+{
+	DB *ddb;
+	DBT key, data;
+	int error, rv, version;
+
+	if ((ddb = dbopen(dbname, O_RDWR|O_CREAT|O_TRUNC, 0644,
+	    DB_BTREE, bti)) == NULL) {
+		warn("creating %s summary", uname);
+		return (-1);
+	}
+
+	error = 0;
+
+	for (rv = DB_SEQ(mdb, &key, &data, R_FIRST);
+	    rv == 0; rv = DB_SEQ(mdb, &key, &data, R_NEXT)) {
+		if ((rv = DB_PUT(ddb, &key, &data, 0)) < 0) {
+			warn("saving %s summary", uname);
+			error = -1;
+			goto out;
+		}
+	}
+	if (rv < 0) {
+		warn("retrieving %s stats", uname);
+		error = -1;
+	}
+
+out:
+	/* Add a version record. */
+	key.data = &VERSION_KEY;
+	key.size = sizeof(VERSION_KEY);
+	version = 2;
+	data.data = &version;
+	data.size = sizeof(version);
+	if ((rv = DB_PUT(ddb, &key, &data, 0)) < 0) {
+		warn("add version record to %s stats", uname);
+		error = -1;
+	} else if (rv == 1) {
+		warnx("duplicate version record in %s stats", uname);
+		error = -1;
+	}
+
+	if (DB_SYNC(ddb, 0) < 0) {
+		warn("syncing %s summary", uname);
+		error = -1;
+	}
+	if (DB_CLOSE(ddb) < 0) {
+		warn("closing %s summary", uname);
+		error = -1;
+	}
+	return error;
+}
+
+void
+db_destroy(DB *db, const char *uname)
+{
+	if (DB_CLOSE(db) < 0)
+		warn("destroying %s stats", uname);
+}


More information about the Midnightbsd-cvs mailing list