4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
30 #pragma ident "%Z%%M% %I% %E% SMI"
34 * reads std. input (acct.h format), adds login names
35 * writes std. output (ptmp.h/ascii format)
36 * if ctmpfile is given, it is expected have ctmp.h/ascii data,
37 * sorted by uid/name; it is used to make better guesses at login names
40 #include <sys/types.h>
41 #include <sys/param.h>
48 #define MYKIND(flag) ((flag & ACCTF) == 0)
54 int a_usize
= A_USIZE
;
55 struct urec
{ /* 1 for each distinct uid/name */
56 uid_t ur_uid
; /* sorted by uid/name */
58 struct srec
*ur_srec
; /* ptr to first session */
59 short ur_cnt
; /* # sessions */
64 int a_ssize
= A_SSIZE
;
67 struct srec
{ /* 1 for each distinct session */
68 dev_t sr_tty
; /* dev, used to connect with process*/
69 time_t sr_start
; /* start time of session */
70 time_t sr_end
; /* end time of session */
73 char *getname(uid_t
, dev_t
, time_t);
74 void readctmp(char *);
75 char *getnamc(uid_t
, dev_t
, time_t);
81 main(int argc
, char **argv
)
87 int ver
; /* version of acct struct */
90 if ((ur
= (struct urec
*) calloc(a_usize
,
91 sizeof (struct urec
))) == NULL
) {
92 fprintf(stderr
, "acctpr1: Cannot allocate memory\n");
97 if ((sr
= (struct srec
*) calloc(a_ssize
,
98 sizeof (struct srec
))) == NULL
) {
99 fprintf(stderr
, "acctpr1: Cannot allocate memory\n");
113 if (fread((char *)&ab
, sizeof(struct acct
), 1, stdin
) != 1)
115 else if (ab
.ac_flag
& AEXPND
)
116 ver
= 2; /* 4.0 acct structure */
118 ver
= 1; /* 3.x acct structure */
122 while (aread(ver
) == 1) {
123 if (!MYKIND(ab
.ac_flag
))
125 pb
.pt_uid
= ab
.ac_uid
;
126 CPYN(pb
.pt_name
, getname(ab
.ac_uid
, ab
.ac_tty
, ab
.ac_btime
));
128 * approximate cpu P/NP split as same as elapsed time
130 if ((etime
= SECS(expand(ab
.ac_etime
))) == 0)
132 stime
= expand(ab
.ac_stime
) + expand(ab
.ac_utime
);
133 mem
= expand(ab
.ac_mem
);
134 if(pnpsplit(ab
.ac_btime
, etime
, elaps
) == 0) {
135 fprintf(stderr
, "acctprc1: could not calculate prime/non-prime hours\n");
139 pb
.pt_cpu
[0] = (double)stime
* (double)elaps
[0] / etime
;
140 pb
.pt_cpu
[1] = (stime
> pb
.pt_cpu
[0])? stime
- pb
.pt_cpu
[0] : 0;
141 pb
.pt_cpu
[1] = stime
- pb
.pt_cpu
[0];
143 pb
.pt_mem
= (mem
+ stime
- 1) / stime
;
145 pb
.pt_mem
= 0; /* unlikely */
146 printf("%ld\t%.*s\t%lu\t%lu\t%u\n",
150 pb
.pt_cpu
[0], pb
.pt_cpu
[1],
158 * return ptr to name corresponding to uid
159 * try ctmp first, then use uidtonam (internal list or passwd file)
162 getname(uid_t uid
, dev_t tty
, time_t start
)
166 if ((p
= getnamc(uid
, tty
, start
)) != NULL
)
168 return (uidtonam(uid
));
172 * read ctmp file, build up urec-srec data structures for
173 * later use by getnamc
176 readctmp(char *fname
)
181 int i
= 0, j
= 0, k
=0;
183 if ((fp
= fopen(fname
, "r")) == NULL
) {
184 fprintf(stderr
, "acctprc1: can't open %s\n", fname
);
191 while (fscanf(fp
, "%hd\t%ld\t%s\t%lu\t%lu\t%lu\t%*[^\n]",
197 &cb
.ct_start
) != EOF
) {
198 if (up
== NULL
|| cb
.ct_uid
!= up
->ur_uid
||
199 !EQN(cb
.ct_name
, up
->ur_name
)) {
202 if (++up
>= &ur
[a_usize
]) {
203 a_usize
= a_usize
+ A_USIZE
;
204 if ((ur
= (struct urec
*) realloc(ur
, a_usize
*
205 sizeof (struct urec
))) == NULL
) {
206 fprintf(stderr
, "acctprc1: 1 Cannot reallocate memory\n");
209 up
= &ur
[a_usize
- A_USIZE
];
211 up
->ur_uid
= cb
.ct_uid
;
212 CPYN(up
->ur_name
, cb
.ct_name
);
217 if (sp
>= &sr
[a_ssize
-1]) {
218 a_ssize
= a_ssize
+ A_SSIZE
;
219 if ((sr
= (struct srec
*) realloc(sr
, a_ssize
*
220 sizeof (struct srec
))) == NULL
) {
221 fprintf(stderr
, "acctprc1: 2 Cannot reallocate memory\n");
222 printf("errno=%d\n", errno
);
225 sp
= &sr
[a_ssize
- A_SSIZE
];
228 sp
->sr_tty
= cb
.ct_tty
;
229 sp
->sr_start
= cb
.ct_start
;
230 sp
->sr_end
= cb
.ct_start
+ cb
.ct_con
[0] + cb
.ct_con
[1];
240 * using urec-srec data (if any), make best guess at login name
241 * corresponding to uid, return ptr to the name.
242 * must match on tty; use start time to help guess
243 * for any urec having same uid as uid, search array of associated
244 * srecs for those having same tty
245 * if start time of process is within range of session, that's it
246 * if none can be found within range, give it to person of same uid
247 * who last logged off on that terminal
250 getnamc(uid_t uid
, dev_t tty
, time_t start
)
260 for (up
= ur
; up
< urlast
&& uid
>= up
->ur_uid
; up
++)
261 if (uid
== up
->ur_uid
) {
263 splast
= sp
+up
->ur_cnt
;
264 for (; sp
< splast
; sp
++)
265 if (tty
== sp
->sr_tty
) {
266 if (start
>= sp
->sr_start
&&
269 if (start
>= sp
->sr_start
&&
270 sp
->sr_end
> latest
) {
286 if ((ret
= fread((char *)&oab
, sizeof(struct o_acct
), 1, stdin
)) == 1){
287 /* copy SVR3 acct struct to SVR4 acct struct */
288 ab
.ac_flag
= oab
.ac_flag
| AEXPND
;
289 ab
.ac_stat
= oab
.ac_stat
;
290 ab
.ac_uid
= (uid_t
) oab
.ac_uid
;
291 ab
.ac_gid
= (gid_t
) oab
.ac_gid
;
292 ab
.ac_tty
= (dev_t
) oab
.ac_tty
;
293 ab
.ac_btime
= oab
.ac_btime
;
294 ab
.ac_utime
= oab
.ac_utime
;
295 ab
.ac_stime
= oab
.ac_stime
;
296 ab
.ac_mem
= oab
.ac_mem
;
297 ab
.ac_io
= oab
.ac_io
;
298 ab
.ac_rw
= oab
.ac_rw
;
299 strcpy(ab
.ac_comm
, oab
.ac_comm
);
302 ret
= fread((char *)&ab
, sizeof(struct acct
), 1, stdin
);
305 return(ret
!= 1 ? 0 : 1);