usrdb.c revision 1.1
1/* 2 * Copyright (c) 1994 Christopher G. Demetriou 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Christopher G. Demetriou. 16 * 4. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#ifndef LINT 32static char rcsid[] = "$Id: usrdb.c,v 1.1 1995/10/18 08:48:07 deraadt Exp $"; 33#endif 34 35#include <sys/types.h> 36#include <sys/acct.h> 37#include <err.h> 38#include <errno.h> 39#include <fcntl.h> 40#include <string.h> 41#include "extern.h" 42#include "pathnames.h" 43 44static int uid_compare __P((const DBT *, const DBT *)); 45 46static DB *usracct_db; 47 48int 49usracct_init() 50{ 51 DB *saved_usracct_db; 52 BTREEINFO bti; 53 int error; 54 55 memset(&bti, 0, sizeof(bti)); 56 bti.compare = uid_compare; 57 58 usracct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, &bti); 59 if (usracct_db == NULL) 60 return (-1); 61 62 error = 0; 63 if (!iflag) { 64 DBT key, data; 65 int serr, nerr; 66 67 saved_usracct_db = dbopen(_PATH_USRACCT, O_RDONLY, 0, DB_BTREE, 68 &bti); 69 if (saved_usracct_db == NULL) { 70 error = (errno == ENOENT) ? 0 : -1; 71 if (error) 72 warn("retrieving user accounting summary"); 73 goto out; 74 } 75 76 serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST); 77 if (serr < 0) { 78 warn("retrieving user accounting summary"); 79 error = -1; 80 goto closeout; 81 } 82 while (serr == 0) { 83 nerr = DB_PUT(usracct_db, &key, &data, 0); 84 if (nerr < 0) { 85 warn("initializing user accounting stats"); 86 error = -1; 87 break; 88 } 89 90 serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT); 91 if (serr < 0) { 92 warn("retrieving user accounting summary"); 93 error = -1; 94 break; 95 } 96 } 97 98closeout: 99 if (DB_CLOSE(saved_usracct_db) < 0) { 100 warn("closing user accounting summary"); 101 error = -1; 102 } 103 } 104 105out: 106 if (error != 0) 107 usracct_destroy(); 108 return (error); 109} 110 111void 112usracct_destroy() 113{ 114 if (DB_CLOSE(usracct_db) < 0) 115 warn("destroying user accounting stats"); 116} 117 118int 119usracct_add(ci) 120 const struct cmdinfo *ci; 121{ 122 DBT key, data; 123 struct userinfo newui; 124 u_long uid; 125 int rv; 126 127 uid = ci->ci_uid; 128 key.data = &uid; 129 key.size = sizeof(uid); 130 131 rv = DB_GET(usracct_db, &key, &data, 0); 132 if (rv < 0) { 133 warn("get key %d from user accounting stats", uid); 134 return (-1); 135 } else if (rv == 0) { /* it's there; copy whole thing */ 136 /* add the old data to the new data */ 137 memcpy(&newui, data.data, data.size); 138 if (newui.ui_uid != uid) { 139 warnx("key %d != expected record number %d", 140 newui.ui_uid, uid); 141 warnx("inconsistent user accounting stats"); 142 return (-1); 143 } 144 } else { /* it's not there; zero it and copy the key */ 145 memset(&newui, 0, sizeof(newui)); 146 newui.ui_uid = ci->ci_uid; 147 } 148 149 newui.ui_calls += ci->ci_calls; 150 newui.ui_utime += ci->ci_utime; 151 newui.ui_stime += ci->ci_stime; 152 newui.ui_mem += ci->ci_mem; 153 newui.ui_io += ci->ci_io; 154 155 data.data = &newui; 156 data.size = sizeof(newui); 157 rv = DB_PUT(usracct_db, &key, &data, 0); 158 if (rv < 0) { 159 warn("add key %d to user accounting stats", uid); 160 return (-1); 161 } else if (rv != 0) { 162 warnx("DB_PUT returned 1"); 163 return (-1); 164 } 165 166 return (0); 167} 168 169int 170usracct_update() 171{ 172 DB *saved_usracct_db; 173 DBT key, data; 174 BTREEINFO bti; 175 u_long uid; 176 int error, serr, nerr; 177 178 memset(&bti, 0, sizeof(bti)); 179 bti.compare = uid_compare; 180 181 saved_usracct_db = dbopen(_PATH_USRACCT, O_RDWR|O_CREAT|O_TRUNC, 0644, 182 DB_BTREE, &bti); 183 if (saved_usracct_db == NULL) { 184 warn("creating user accounting summary"); 185 return (-1); 186 } 187 188 error = 0; 189 190 serr = DB_SEQ(usracct_db, &key, &data, R_FIRST); 191 if (serr < 0) { 192 warn("retrieving user accounting stats"); 193 error = -1; 194 } 195 while (serr == 0) { 196 nerr = DB_PUT(saved_usracct_db, &key, &data, 0); 197 if (nerr < 0) { 198 warn("saving user accounting summary"); 199 error = -1; 200 break; 201 } 202 203 serr = DB_SEQ(usracct_db, &key, &data, R_NEXT); 204 if (serr < 0) { 205 warn("retrieving user accounting stats"); 206 error = -1; 207 break; 208 } 209 } 210 211 if (DB_SYNC(saved_usracct_db, 0) < 0) { 212 warn("syncing process accounting summary"); 213 error = -1; 214 } 215out: 216 if (DB_CLOSE(saved_usracct_db) < 0) { 217 warn("closing process accounting summary"); 218 error = -1; 219 } 220 return error; 221} 222 223void 224usracct_print() 225{ 226 DBT key, data; 227 struct userinfo uistore, *ui = &uistore; 228 double t; 229 int rv; 230 231 rv = DB_SEQ(usracct_db, &key, &data, R_FIRST); 232 if (rv < 0) 233 warn("retrieving user accounting stats"); 234 235 while (rv == 0) { 236 memcpy(ui, data.data, sizeof(struct userinfo)); 237 238 printf("%-8s %9qu ", 239 user_from_uid(ui->ui_uid, 0), ui->ui_calls); 240 241 t = (double) (ui->ui_utime + ui->ui_stime) / 242 (double) AHZ; 243 if (t < 0.0001) /* kill divide by zero */ 244 t = 0.0001; 245 246 printf("%12.2lf%s ", t / 60.0, "cpu"); 247 248 /* ui->ui_calls is always != 0 */ 249 if (dflag) 250 printf("%12qu%s", ui->ui_io / ui->ui_calls, "avio"); 251 else 252 printf("%12qu%s", ui->ui_io, "tio"); 253 254 /* t is always >= 0.0001; see above */ 255 if (kflag) 256 printf("%12qu%s", ui->ui_mem / t, "k"); 257 else 258 printf("%12qu%s", ui->ui_mem, "k*sec"); 259 260 printf("\n"); 261 262 rv = DB_SEQ(usracct_db, &key, &data, R_NEXT); 263 if (rv < 0) 264 warn("retrieving user accounting stats"); 265 } 266} 267 268static int 269uid_compare(k1, k2) 270 const DBT *k1, *k2; 271{ 272 u_long d1, d2; 273 274 memcpy(&d1, k1->data, sizeof(d1)); 275 memcpy(&d2, k2->data, sizeof(d2)); 276 277 if (d1 < d2) 278 return -1; 279 else if (d1 == d2) 280 return 0; 281 else 282 return 1; 283} 284