usrdb.c revision 8857
13125Sdg/* 23125Sdg * Copyright (c) 1994 Christopher G. Demetriou 33125Sdg * All rights reserved. 43125Sdg * 53125Sdg * Redistribution and use in source and binary forms, with or without 63125Sdg * modification, are permitted provided that the following conditions 73125Sdg * are met: 83125Sdg * 1. Redistributions of source code must retain the above copyright 93125Sdg * notice, this list of conditions and the following disclaimer. 103125Sdg * 2. Redistributions in binary form must reproduce the above copyright 113125Sdg * notice, this list of conditions and the following disclaimer in the 123125Sdg * documentation and/or other materials provided with the distribution. 133125Sdg * 3. All advertising materials mentioning features or use of this software 143125Sdg * must display the following acknowledgement: 153125Sdg * This product includes software developed by Christopher G. Demetriou. 163125Sdg * 4. The name of the author may not be used to endorse or promote products 173125Sdg * derived from this software without specific prior written permission 183125Sdg * 193125Sdg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 203125Sdg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 213125Sdg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 223125Sdg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 233125Sdg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 243125Sdg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 253125Sdg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 263125Sdg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 273125Sdg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 283125Sdg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 293125Sdg */ 303125Sdg 313125Sdg#ifndef LINT 328857Srgrimesstatic char rcsid[] = "$Id: usrdb.c,v 1.1.1.1 1994/09/26 21:22:57 davidg Exp $"; 333125Sdg#endif 343125Sdg 353125Sdg#include <sys/types.h> 363125Sdg#include <sys/acct.h> 373125Sdg#include <err.h> 383125Sdg#include <errno.h> 393125Sdg#include <fcntl.h> 403125Sdg#include "extern.h" 413125Sdg#include "pathnames.h" 423125Sdg 433125Sdgstatic int uid_compare __P((const DBT *, const DBT *)); 443125Sdg 453125Sdgstatic DB *usracct_db; 463125Sdg 473125Sdgint 483125Sdgusracct_init() 493125Sdg{ 503125Sdg DB *saved_usracct_db; 513125Sdg BTREEINFO bti; 523125Sdg int error; 533125Sdg 543125Sdg bzero(&bti, sizeof bti); 553125Sdg bti.compare = uid_compare; 563125Sdg 573125Sdg usracct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, &bti); 583125Sdg if (usracct_db == NULL) 593125Sdg return (-1); 603125Sdg 613125Sdg error = 0; 623125Sdg if (!iflag) { 633125Sdg DBT key, data; 643125Sdg int serr, nerr; 653125Sdg 663125Sdg saved_usracct_db = dbopen(_PATH_USRACCT, O_RDONLY, 0, DB_BTREE, 673125Sdg &bti); 683125Sdg if (saved_usracct_db == NULL) { 693125Sdg error = (errno == ENOENT) ? 0 : -1; 703125Sdg if (error) 713125Sdg warn("retrieving user accounting summary"); 723125Sdg goto out; 733125Sdg } 743125Sdg 753125Sdg serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST); 763125Sdg if (serr < 0) { 773125Sdg warn("retrieving user accounting summary"); 783125Sdg error = -1; 793125Sdg goto closeout; 803125Sdg } 813125Sdg while (serr == 0) { 823125Sdg nerr = DB_PUT(usracct_db, &key, &data, 0); 833125Sdg if (nerr < 0) { 843125Sdg warn("initializing user accounting stats"); 853125Sdg error = -1; 863125Sdg break; 878857Srgrimes } 883125Sdg 893125Sdg serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT); 903125Sdg if (serr < 0) { 913125Sdg warn("retrieving user accounting summary"); 923125Sdg error = -1; 933125Sdg break; 943125Sdg } 953125Sdg } 963125Sdg 973125Sdgcloseout: 983125Sdg if (DB_CLOSE(saved_usracct_db) < 0) { 993125Sdg warn("closing user accounting summary"); 1003125Sdg error = -1; 1013125Sdg } 1023125Sdg } 1033125Sdg 1043125Sdgout: 1053125Sdg if (error != 0) 1063125Sdg usracct_destroy(); 1073125Sdg return (error); 1083125Sdg} 1093125Sdg 1103125Sdgvoid 1113125Sdgusracct_destroy() 1123125Sdg{ 1133125Sdg if (DB_CLOSE(usracct_db) < 0) 1143125Sdg warn("destroying user accounting stats"); 1153125Sdg} 1163125Sdg 1173125Sdgint 1183125Sdgusracct_add(ci) 1193125Sdg const struct cmdinfo *ci; 1203125Sdg{ 1213125Sdg DBT key, data; 1223125Sdg struct userinfo newui; 1233125Sdg u_long uid; 1243125Sdg int rv; 1253125Sdg 1263125Sdg uid = ci->ci_uid; 1273125Sdg key.data = &uid; 1283125Sdg key.size = sizeof uid; 1293125Sdg 1303125Sdg rv = DB_GET(usracct_db, &key, &data, 0); 1313125Sdg if (rv < 0) { 1323125Sdg warn("get key %d from user accounting stats", uid); 1333125Sdg return (-1); 1343125Sdg } else if (rv == 0) { /* it's there; copy whole thing */ 1353125Sdg /* add the old data to the new data */ 1363125Sdg bcopy(data.data, &newui, data.size); 1373125Sdg if (newui.ui_uid != uid) { 1383125Sdg warnx("key %d != expected record number %d", 1393125Sdg newui.ui_uid, uid); 1403125Sdg warnx("inconsistent user accounting stats"); 1413125Sdg return (-1); 1423125Sdg } 1433125Sdg } else { /* it's not there; zero it and copy the key */ 1443125Sdg bzero(&newui, sizeof newui); 1453125Sdg newui.ui_uid = ci->ci_uid; 1463125Sdg } 1473125Sdg 1483125Sdg newui.ui_calls += ci->ci_calls; 1493125Sdg newui.ui_utime += ci->ci_utime; 1503125Sdg newui.ui_stime += ci->ci_stime; 1513125Sdg newui.ui_mem += ci->ci_mem; 1523125Sdg newui.ui_io += ci->ci_io; 1533125Sdg 1548857Srgrimes data.data = &newui; 1553125Sdg data.size = sizeof newui; 1563125Sdg rv = DB_PUT(usracct_db, &key, &data, 0); 1573125Sdg if (rv < 0) { 1583125Sdg warn("add key %d to user accounting stats", uid); 1593125Sdg return (-1); 1603125Sdg } else if (rv != 0) { 1613125Sdg warnx("DB_PUT returned 1"); 1623125Sdg return (-1); 1633125Sdg } 1643125Sdg 1653125Sdg return (0); 1663125Sdg} 1673125Sdg 1683125Sdgint 1693125Sdgusracct_update() 1703125Sdg{ 1713125Sdg DB *saved_usracct_db; 1723125Sdg DBT key, data; 1733125Sdg BTREEINFO bti; 1743125Sdg u_long uid; 1753125Sdg int error, serr, nerr; 1763125Sdg 1773125Sdg bzero(&bti, sizeof bti); 1783125Sdg bti.compare = uid_compare; 1793125Sdg 1803125Sdg saved_usracct_db = dbopen(_PATH_USRACCT, O_RDWR|O_CREAT|O_TRUNC, 0644, 1813125Sdg DB_BTREE, &bti); 1823125Sdg if (saved_usracct_db == NULL) { 1833125Sdg warn("creating user accounting summary"); 1843125Sdg return (-1); 1853125Sdg } 1863125Sdg 1873125Sdg error = 0; 1883125Sdg 1893125Sdg serr = DB_SEQ(usracct_db, &key, &data, R_FIRST); 1903125Sdg if (serr < 0) { 1913125Sdg warn("retrieving user accounting stats"); 1923125Sdg error = -1; 1933125Sdg } 1943125Sdg while (serr == 0) { 1953125Sdg nerr = DB_PUT(saved_usracct_db, &key, &data, 0); 1963125Sdg if (nerr < 0) { 1973125Sdg warn("saving user accounting summary"); 1983125Sdg error = -1; 1993125Sdg break; 2003125Sdg } 2013125Sdg 2023125Sdg serr = DB_SEQ(usracct_db, &key, &data, R_NEXT); 2033125Sdg if (serr < 0) { 2043125Sdg warn("retrieving user accounting stats"); 2053125Sdg error = -1; 2063125Sdg break; 2073125Sdg } 2083125Sdg } 2093125Sdg 2103125Sdg if (DB_SYNC(saved_usracct_db, 0) < 0) { 2113125Sdg warn("syncing process accounting summary"); 2123125Sdg error = -1; 2133125Sdg } 2143125Sdgout: 2153125Sdg if (DB_CLOSE(saved_usracct_db) < 0) { 2163125Sdg warn("closing process accounting summary"); 2173125Sdg error = -1; 2183125Sdg } 2193125Sdg return error; 2203125Sdg} 2213125Sdg 2223125Sdgvoid 2233125Sdgusracct_print() 2243125Sdg{ 2253125Sdg DBT key, data; 2263125Sdg struct userinfo *ui; 2273125Sdg double t; 2283125Sdg int rv; 2293125Sdg 2303125Sdg rv = DB_SEQ(usracct_db, &key, &data, R_FIRST); 2313125Sdg if (rv < 0) 2323125Sdg warn("retrieving user accounting stats"); 2333125Sdg 2343125Sdg while (rv == 0) { 2353125Sdg ui = (struct userinfo *) data.data; 2363125Sdg 2373125Sdg printf("%-8s %9qu ", 2383125Sdg user_from_uid(ui->ui_uid, 0), ui->ui_calls); 2393125Sdg 2403125Sdg t = (double) (ui->ui_utime + ui->ui_stime) / 2413125Sdg (double) AHZ; 2423125Sdg if (t < 0.0001) /* kill divide by zero */ 2433125Sdg t = 0.0001; 2443125Sdg 2453125Sdg printf("%12.2lf%s ", t / 60.0, "cpu"); 2463125Sdg 2473125Sdg /* ui->ui_calls is always != 0 */ 2483125Sdg if (dflag) 2493125Sdg printf("%12qu%s", ui->ui_io / ui->ui_calls, "avio"); 2503125Sdg else 2513125Sdg printf("%12qu%s", ui->ui_io, "tio"); 2523125Sdg 2533125Sdg /* t is always >= 0.0001; see above */ 2543125Sdg if (kflag) 2553125Sdg printf("%12qu%s", ui->ui_mem / t, "k"); 2563125Sdg else 2573125Sdg printf("%12qu%s", ui->ui_mem, "k*sec"); 2583125Sdg 2593125Sdg printf("\n"); 2603125Sdg 2613125Sdg rv = DB_SEQ(usracct_db, &key, &data, R_NEXT); 2623125Sdg if (rv < 0) 2633125Sdg warn("retrieving user accounting stats"); 2643125Sdg } 2653125Sdg} 2663125Sdg 2673125Sdgstatic int 2683125Sdguid_compare(k1, k2) 2693125Sdg const DBT *k1, *k2; 2703125Sdg{ 2713125Sdg u_long d1, d2; 2723125Sdg 2733125Sdg bcopy(k1->data, &d1, sizeof d1); 2743125Sdg bcopy(k2->data, &d2, sizeof d2); 2758857Srgrimes 2763125Sdg if (d1 < d2) 2773125Sdg return -1; 2783125Sdg else if (d1 == d2) 2793125Sdg return 0; 2803125Sdg else 2813125Sdg return 1; 2823125Sdg} 283