summaryrefslogtreecommitdiffstats
path: root/system_cmds/sa.tproj/usrdb.c
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
commit5fd83771641d15c418f747bd343ba6738d3875f7 (patch)
tree5abf0f78f680d9837dbd93d4d4c3933bb7509599 /system_cmds/sa.tproj/usrdb.c
downloadapple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip
Import macOS userland
adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106
Diffstat (limited to 'system_cmds/sa.tproj/usrdb.c')
-rw-r--r--system_cmds/sa.tproj/usrdb.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/system_cmds/sa.tproj/usrdb.c b/system_cmds/sa.tproj/usrdb.c
new file mode 100644
index 0000000..e47220a
--- /dev/null
+++ b/system_cmds/sa.tproj/usrdb.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 1994 Christopher G. Demetriou
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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/usrdb.c,v 1.16 2007/05/22 06:51:38 dds Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/acct.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "extern.h"
+#include "pathnames.h"
+
+static int uid_compare(const DBT *, const DBT *);
+
+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(void)
+{
+ BTREEINFO bti;
+
+ bzero(&bti, sizeof bti);
+ bti.compare = uid_compare;
+
+ return (db_copy_in(&usracct_db, usrdb_file, "user accounting",
+ &bti, v1_to_v2));
+}
+
+void
+usracct_destroy(void)
+{
+ db_destroy(usracct_db, "user accounting");
+}
+
+int
+usracct_add(const struct cmdinfo *ci)
+{
+ DBT key, data;
+ struct userinfo newui;
+ uid_t uid;
+ int rv;
+
+ uid = ci->ci_uid;
+ key.data = &uid;
+ key.size = sizeof uid;
+
+ rv = DB_GET(usracct_db, &key, &data, 0);
+ if (rv < 0) {
+ 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 %u != expected record number %u",
+ newui.ui_uid, uid);
+ warnx("inconsistent user accounting stats");
+ return (-1);
+ }
+ } else { /* it's not there; zero it and copy the key */
+ bzero(&newui, sizeof newui);
+ newui.ui_uid = ci->ci_uid;
+ }
+
+ newui.ui_calls += ci->ci_calls;
+ newui.ui_utime += ci->ci_utime;
+ newui.ui_stime += ci->ci_stime;
+ newui.ui_mem += ci->ci_mem;
+ newui.ui_io += ci->ci_io;
+
+ data.data = &newui;
+ data.size = sizeof newui;
+ rv = DB_PUT(usracct_db, &key, &data, 0);
+ if (rv < 0) {
+ warn("add key %u to user accounting stats", uid);
+ return (-1);
+ } else if (rv != 0) {
+ warnx("DB_PUT returned 1");
+ return (-1);
+ }
+
+ return (0);
+}
+
+/* Copy in-memory usracct_db to usrdb_file. */
+int
+usracct_update(void)
+{
+ BTREEINFO bti;
+
+ bzero(&bti, sizeof bti);
+ bti.compare = uid_compare;
+
+ return (db_copy_out(usracct_db, usrdb_file, "user accounting",
+ &bti));
+}
+
+void
+usracct_print(void)
+{
+ DBT key, data;
+ struct userinfo uistore, *ui = &uistore;
+ double t;
+ int rv;
+
+ rv = DB_SEQ(usracct_db, &key, &data, R_FIRST);
+ if (rv < 0)
+ warn("retrieving user accounting stats");
+
+ while (rv == 0) {
+ memcpy(ui, data.data, sizeof(struct userinfo));
+
+ printf("%-*s %9ju ", MAXLOGNAME - 1,
+ user_from_uid(ui->ui_uid, 0), (uintmax_t)ui->ui_calls);
+
+#ifdef __APPLE__
+ t = (double) (ui->ui_utime + ui->ui_stime) /
+ (double) AHZ;
+ if (t < 0.0001) /* kill divide by zero */
+ t = 0.0001;
+
+ 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");
+ else
+ printf("%12ju%s", (uintmax_t)ui->ui_io, "tio");
+
+ /* t is always >= 0.0001; see above */
+ if (kflag)
+ printf("%12.0f%s", ui->ui_mem / t, "k");
+ else
+ printf("%12ju%s", (uintmax_t)ui->ui_mem, "k*sec");
+#else
+ 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("%12.0f%s",
+ ui->ui_io / ui->ui_calls, "avio");
+ else
+ printf("%12.0f%s", ui->ui_io, "tio");
+
+ /* t is always >= 0.000001; see above. */
+ if (kflag)
+ printf("%12.0f%s", ui->ui_mem / t, "k");
+ else
+ printf("%12.0f%s", ui->ui_mem, "k*sec");
+#endif
+
+ printf("\n");
+
+ rv = DB_SEQ(usracct_db, &key, &data, R_NEXT);
+ if (rv < 0)
+ warn("retrieving user accounting stats");
+ }
+}
+
+static int
+uid_compare(const DBT *k1, const DBT *k2)
+{
+ uid_t d1, d2;
+
+ bcopy(k1->data, &d1, sizeof d1);
+ bcopy(k2->data, &d2, sizeof d2);
+
+ if (d1 < d2)
+ return -1;
+ else if (d1 == d2)
+ return 0;
+ else
+ return 1;
+}