usrdb.c (5f6f6b2933fa608f6dd5c8d9769eba8b8d5e9c2b) usrdb.c (fdbe5babe4c36438757554fd0b61ff7ba19b0dc2)
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

--- 35 unchanged lines hidden (view full) ---

44#include <string.h>
45#include "extern.h"
46#include "pathnames.h"
47
48static int uid_compare(const DBT *, const DBT *);
49
50static DB *usracct_db;
51
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

--- 35 unchanged lines hidden (view full) ---

44#include <string.h>
45#include "extern.h"
46#include "pathnames.h"
47
48static int uid_compare(const DBT *, const DBT *);
49
50static DB *usracct_db;
51
52int
53usracct_init()
52/* Legacy format in AHZV1 units. */
53struct userinfov1 {
54 uid_t ui_uid; /* user id; for consistency */
55 u_quad_t ui_calls; /* number of invocations */
56 u_quad_t ui_utime; /* user time */
57 u_quad_t ui_stime; /* system time */
58 u_quad_t ui_mem; /* memory use */
59 u_quad_t ui_io; /* number of disk i/o ops */
60};
61
62/*
63 * Convert a v1 data record into the current version.
64 * Return 0 if OK, -1 on error, setting errno.
65 */
66static int
67v1_to_v2(DBT *key, DBT *data)
54{
68{
55 DB *saved_usracct_db;
56 BTREEINFO bti;
57 int error;
69 struct userinfov1 uiv1;
70 static struct userinfo uiv2;
71 static uid_t uid;
58
72
59 bzero(&bti, sizeof bti);
60 bti.compare = uid_compare;
61
62 usracct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, &bti);
63 if (usracct_db == NULL)
73 if (key->size != sizeof(u_long) || data->size != sizeof(uiv1)) {
74 errno = EFTYPE;
64 return (-1);
75 return (-1);
76 }
65
77
66 error = 0;
67 if (!iflag) {
68 DBT key, data;
69 int serr, nerr;
78 /* Convert key. */
79 key->size = sizeof(uid_t);
80 uid = (uid_t)*(u_long *)(key->data);
81 key->data = &uid;
70
82
71 saved_usracct_db = dbopen(usrdb_file, O_RDONLY, 0, DB_BTREE,
72 &bti);
73 if (saved_usracct_db == NULL) {
74 error = (errno == ENOENT) ? 0 : -1;
75 if (error)
76 warn("retrieving user accounting summary");
77 goto out;
78 }
83 /* Convert data. */
84 memcpy(&uiv1, data->data, data->size);
85 memset(&uiv2, 0, sizeof(uiv2));
86 uiv2.ui_uid = uiv1.ui_uid;
87 uiv2.ui_calls = uiv1.ui_calls;
88 uiv2.ui_utime = ((double)uiv1.ui_utime / AHZV1) * 1000000;
89 uiv2.ui_stime = ((double)uiv1.ui_stime / AHZV1) * 1000000;
90 uiv2.ui_mem = uiv1.ui_mem;
91 uiv2.ui_io = uiv1.ui_io;
92 data->size = sizeof(uiv2);
93 data->data = &uiv2;
79
94
80 serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST);
81 if (serr < 0) {
82 warn("retrieving user accounting summary");
83 error = -1;
84 goto closeout;
85 }
86 while (serr == 0) {
87 nerr = DB_PUT(usracct_db, &key, &data, 0);
88 if (nerr < 0) {
89 warn("initializing user accounting stats");
90 error = -1;
91 break;
92 }
95 return (0);
96}
93
97
94 serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT);
95 if (serr < 0) {
96 warn("retrieving user accounting summary");
97 error = -1;
98 break;
99 }
100 }
98/* Copy usrdb_file to in-memory usracct_db. */
99int
100usracct_init()
101{
102 BTREEINFO bti;
101
103
102closeout:
103 if (DB_CLOSE(saved_usracct_db) < 0) {
104 warn("closing user accounting summary");
105 error = -1;
106 }
107 }
104 bzero(&bti, sizeof bti);
105 bti.compare = uid_compare;
108
106
109out:
110 if (error != 0)
111 usracct_destroy();
112 return (error);
107 return (db_copy_in(&usracct_db, usrdb_file, "user accounting",
108 &bti, v1_to_v2));
113}
114
115void
116usracct_destroy()
117{
109}
110
111void
112usracct_destroy()
113{
118 if (DB_CLOSE(usracct_db) < 0)
119 warn("destroying user accounting stats");
114 db_destroy(usracct_db, "user accounting");
120}
121
122int
123usracct_add(const struct cmdinfo *ci)
124{
125 DBT key, data;
126 struct userinfo newui;
115}
116
117int
118usracct_add(const struct cmdinfo *ci)
119{
120 DBT key, data;
121 struct userinfo newui;
127 u_long uid;
122 uid_t uid;
128 int rv;
129
130 uid = ci->ci_uid;
131 key.data = &uid;
132 key.size = sizeof uid;
133
134 rv = DB_GET(usracct_db, &key, &data, 0);
135 if (rv < 0) {
123 int rv;
124
125 uid = ci->ci_uid;
126 key.data = &uid;
127 key.size = sizeof uid;
128
129 rv = DB_GET(usracct_db, &key, &data, 0);
130 if (rv < 0) {
136 warn("get key %lu from user accounting stats", uid);
131 warn("get key %u from user accounting stats", uid);
137 return (-1);
138 } else if (rv == 0) { /* it's there; copy whole thing */
139 /* add the old data to the new data */
140 bcopy(data.data, &newui, data.size);
141 if (newui.ui_uid != uid) {
132 return (-1);
133 } else if (rv == 0) { /* it's there; copy whole thing */
134 /* add the old data to the new data */
135 bcopy(data.data, &newui, data.size);
136 if (newui.ui_uid != uid) {
142 warnx("key %lu != expected record number %lu",
137 warnx("key %u != expected record number %u",
143 newui.ui_uid, uid);
144 warnx("inconsistent user accounting stats");
145 return (-1);
146 }
147 } else { /* it's not there; zero it and copy the key */
148 bzero(&newui, sizeof newui);
149 newui.ui_uid = ci->ci_uid;
150 }
151
152 newui.ui_calls += ci->ci_calls;
153 newui.ui_utime += ci->ci_utime;
154 newui.ui_stime += ci->ci_stime;
155 newui.ui_mem += ci->ci_mem;
156 newui.ui_io += ci->ci_io;
157
158 data.data = &newui;
159 data.size = sizeof newui;
160 rv = DB_PUT(usracct_db, &key, &data, 0);
161 if (rv < 0) {
138 newui.ui_uid, uid);
139 warnx("inconsistent user accounting stats");
140 return (-1);
141 }
142 } else { /* it's not there; zero it and copy the key */
143 bzero(&newui, sizeof newui);
144 newui.ui_uid = ci->ci_uid;
145 }
146
147 newui.ui_calls += ci->ci_calls;
148 newui.ui_utime += ci->ci_utime;
149 newui.ui_stime += ci->ci_stime;
150 newui.ui_mem += ci->ci_mem;
151 newui.ui_io += ci->ci_io;
152
153 data.data = &newui;
154 data.size = sizeof newui;
155 rv = DB_PUT(usracct_db, &key, &data, 0);
156 if (rv < 0) {
162 warn("add key %lu to user accounting stats", uid);
157 warn("add key %u to user accounting stats", uid);
163 return (-1);
164 } else if (rv != 0) {
165 warnx("DB_PUT returned 1");
166 return (-1);
167 }
168
169 return (0);
170}
171
158 return (-1);
159 } else if (rv != 0) {
160 warnx("DB_PUT returned 1");
161 return (-1);
162 }
163
164 return (0);
165}
166
167/* Copy in-memory usracct_db to usrdb_file. */
172int
173usracct_update()
174{
168int
169usracct_update()
170{
175 DB *saved_usracct_db;
176 DBT key, data;
177 BTREEINFO bti;
171 BTREEINFO bti;
178 int error, serr, nerr;
179
180 bzero(&bti, sizeof bti);
181 bti.compare = uid_compare;
182
172
173 bzero(&bti, sizeof bti);
174 bti.compare = uid_compare;
175
183 saved_usracct_db = dbopen(usrdb_file, O_RDWR|O_CREAT|O_TRUNC, 0644,
184 DB_BTREE, &bti);
185 if (saved_usracct_db == NULL) {
186 warn("creating user accounting summary");
187 return (-1);
188 }
189
190 error = 0;
191
192 serr = DB_SEQ(usracct_db, &key, &data, R_FIRST);
193 if (serr < 0) {
194 warn("retrieving user accounting stats");
195 error = -1;
196 }
197 while (serr == 0) {
198 nerr = DB_PUT(saved_usracct_db, &key, &data, 0);
199 if (nerr < 0) {
200 warn("saving user accounting summary");
201 error = -1;
202 break;
203 }
204
205 serr = DB_SEQ(usracct_db, &key, &data, R_NEXT);
206 if (serr < 0) {
207 warn("retrieving user accounting stats");
208 error = -1;
209 break;
210 }
211 }
212
213 if (DB_SYNC(saved_usracct_db, 0) < 0) {
214 warn("syncing process accounting summary");
215 error = -1;
216 }
217 if (DB_CLOSE(saved_usracct_db) < 0) {
218 warn("closing process accounting summary");
219 error = -1;
220 }
221 return error;
176 return (db_copy_out(usracct_db, usrdb_file, "user accounting",
177 &bti));
222}
223
224void
225usracct_print()
226{
227 DBT key, data;
228 struct userinfo uistore, *ui = &uistore;
229 double t;

--- 4 unchanged lines hidden (view full) ---

234 warn("retrieving user accounting stats");
235
236 while (rv == 0) {
237 memcpy(ui, data.data, sizeof(struct userinfo));
238
239 printf("%-*s %9ju ", MAXLOGNAME - 1,
240 user_from_uid(ui->ui_uid, 0), (uintmax_t)ui->ui_calls);
241
178}
179
180void
181usracct_print()
182{
183 DBT key, data;
184 struct userinfo uistore, *ui = &uistore;
185 double t;

--- 4 unchanged lines hidden (view full) ---

190 warn("retrieving user accounting stats");
191
192 while (rv == 0) {
193 memcpy(ui, data.data, sizeof(struct userinfo));
194
195 printf("%-*s %9ju ", MAXLOGNAME - 1,
196 user_from_uid(ui->ui_uid, 0), (uintmax_t)ui->ui_calls);
197
242 t = (double) (ui->ui_utime + ui->ui_stime) /
243 (double) AHZ;
244 if (t < 0.0001) /* kill divide by zero */
245 t = 0.0001;
198 t = (ui->ui_utime + ui->ui_stime) / 1000000;
199 if (t < 0.000001) /* kill divide by zero */
200 t = 0.000001;
246
247 printf("%12.2f%s ", t / 60.0, "cpu");
248
249 /* ui->ui_calls is always != 0 */
250 if (dflag)
201
202 printf("%12.2f%s ", t / 60.0, "cpu");
203
204 /* ui->ui_calls is always != 0 */
205 if (dflag)
251 printf("%12ju%s",
252 (uintmax_t)(ui->ui_io / ui->ui_calls), "avio");
206 printf("%12.0f%s",
207 ui->ui_io / ui->ui_calls, "avio");
253 else
208 else
254 printf("%12ju%s", (uintmax_t)ui->ui_io, "tio");
209 printf("%12.0f%s", ui->ui_io, "tio");
255
210
256 /* t is always >= 0.0001; see above */
211 /* t is always >= 0.000001; see above. */
257 if (kflag)
258 printf("%12.0f%s", ui->ui_mem / t, "k");
259 else
212 if (kflag)
213 printf("%12.0f%s", ui->ui_mem / t, "k");
214 else
260 printf("%12ju%s", (uintmax_t)ui->ui_mem, "k*sec");
215 printf("%12.0f%s", ui->ui_mem, "k*sec");
261
262 printf("\n");
263
264 rv = DB_SEQ(usracct_db, &key, &data, R_NEXT);
265 if (rv < 0)
266 warn("retrieving user accounting stats");
267 }
268}
269
270static int
271uid_compare(const DBT *k1, const DBT *k2)
272{
216
217 printf("\n");
218
219 rv = DB_SEQ(usracct_db, &key, &data, R_NEXT);
220 if (rv < 0)
221 warn("retrieving user accounting stats");
222 }
223}
224
225static int
226uid_compare(const DBT *k1, const DBT *k2)
227{
273 u_long d1, d2;
228 uid_t d1, d2;
274
275 bcopy(k1->data, &d1, sizeof d1);
276 bcopy(k2->data, &d2, sizeof d2);
277
278 if (d1 < d2)
279 return -1;
280 else if (d1 == d2)
281 return 0;
282 else
283 return 1;
284}
229
230 bcopy(k1->data, &d1, sizeof d1);
231 bcopy(k2->data, &d2, sizeof d2);
232
233 if (d1 < d2)
234 return -1;
235 else if (d1 == d2)
236 return 0;
237 else
238 return 1;
239}