diff options
author | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
---|---|---|
committer | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
commit | 5fd83771641d15c418f747bd343ba6738d3875f7 (patch) | |
tree | 5abf0f78f680d9837dbd93d4d4c3933bb7509599 /system_cmds/sa.tproj/usrdb.c | |
download | apple_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.c | 261 |
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; +} |