Perl unpack/tacct file
Todd Ogasawara
todd at pinhead.pegasus.com
Tue May 7 09:57:54 AEST 1991
I posted a query last week. No responses so far, but I found a
workaround. My question now is, "Why does my workaround work?"
Here is my original posting.
In article <1991May04.185409.24228 at pinhead.pegasus.com> todd at pinhead.pegasus.com (Todd Ogasawara) writes:
]I just started using Perl a few weeks ago and have run into a problem when
]trying to use unpack to look at 'tacct' type accounting files on an 386 box
]running Interactive UNIX 2.2 (UNIX System V/386 R3). I'm pretty sure I
]understand the structure of this file type since C programs I've written to
]read it work fine. The C structure of this file looks like this:
]#p = prime time, np = non-prime time
]#struct tacct {
]# unsigned short ta_uid; /* userid */
]# char ta_name[8]; /* login name */
]# float ta_cpu[2]; /* cum cpu time, p/np (mins) */
]# float ta_kcore[2]; /* cum kcore-minutes, p/np */
]# float ta_con[2]; /* cum connect time p/np, mins */
]# float ta_du; /* cum disk usage */
]# long ta_pc; /* count of processes */
]# unsigned short ta_sc; /* count of login sessions */
]# unsigned short ta_dc; /* count of disk samples */
]# unsigned short ta_fee; /* fee for special services */
]#};
]
]Here's the perl program I've tried to use to read a tacct file with. (BTW,
]I'm using Perl 4.0 patch level 3).
]
]open(TACCT,"/usr/adm/acct/sum/tacct");
]
]while(read(TACCT,$tacct,52)) {
] ($uid,$name,$cpuP,$cpuNP,$kcoreP,$kcoreNP,$conP,$conNP,
] $du,$pc,$sc,$dc,$fee) =
] unpack("S A8 f f f f f f f l S S S",$tacct);
] local($TCONNECT) = $conP + $conNP;
] printf "%4d %8s %7.2f %d %d\n",
] $uid, $name, $TCONNECT, $sc, $dc;
]}
]
]The $uid and $name variables contain what I expect it to. However,
]everything else that follows seems to be one off. I.e., The $dc variable
]should contain the number of disk samples but seems to contain the number
]of login sessions instead. The floating point values are all over the
]place. I know that I must be reading in the floating point variables
]incorrectly, but I don't know what it is that I'm doing wrong. BTW, I have
]the Wall & Schwartz "Programming Perl" book and have gone through the
]sections describing pack and unpack several times to try to understand what
]is going on here.
The following Perl program reads tacct type files correctly. My only
problem is I don't understand why it works. I had to place two skips of x2
in the unpack template (see $stbuf_def) to get the program to work. I'm
pretty sure my problem is not understanding exactly how C structures are
built. I found that a C sizeof(tacctstruct) told me the structure is 52
bytes large. However, when I added the size of each individual structure
member it added up to 48 bytes. I had to do a hex dump to find that there
were four bytes in two places (two bytes in each place) that never seemed
to be used. Is there some easy rule I can follow when using Perl to unpack
files created using C structures?
#! /usr/local/bin/perl
open(TACCT,"/usr/adm/acct/sum/tacct");
$stbuf_def = "SA8x2f2f2f2flS3x2";
$streclen = length(pack($stbuf_def, 0));
print " UID NAME cpuP cpuNP conP conNP disksamp login\n";
while(read(TACCT,$tacct,$streclen)) {
($uid,$name,$cpuP,$cpuNP,$kcoreP,$kcoreNP,$conP,$conNP,
$du,$pc,$sc,$dc,$fee) =
unpack($stbuf_def,$tacct);
printf "%4d %8s %9.2f %9.2f %7.2f %7.2f %9.2f %4d\n",
$uid, $name, $cpuP, $cpuNP, $conP, $conNP, $du, $sc;
}
--
Todd Ogasawara ::: Hawaii Medical Service Association
Internet ::: todd at pinhead.pegasus.com
Telephone ::: (808) 536-9162 ext. 7
More information about the Comp.unix.sysv386
mailing list