todd@pinhead.pegasus.com (Todd Ogasawara) (05/05/91)
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.
Thanks for any help/hints anyone can offer.
--
Todd Ogasawara ::: Hawaii Medical Service Association
Internet ::: todd@pinhead.pegasus.com
Telephone ::: (808) 536-9162 ext. 7
jdeitch@jadpc.cts.com (Jim Deitch) (05/05/91)
In article <1991May04.185409.24228@pinhead.pegasus.com> todd@pinhead.pegasus.com (Todd Ogasawara) writes: > >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). > ^^^^^^^^^^^^^^^^^^^^^^ I saw this was available, but the message went by to fast. Where can I get a copy ? Jim -- ARPANET: jadpc!jdeitch@nosc.mil INTERNET: jdeitch@jadpc.cts.com UUCP: nosc!jadpc!jdeitch
lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (05/07/91)
In article <1991May04.185409.24228@pinhead.pegasus.com> todd@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.
Your C compiler is probably throwing you a curve by aligning the first
float to a 4-byte boundary. Try saying
unpack("S A8 x2 f f f f f f f l S S S",$tacct);
Larry
todd@pinhead.pegasus.com (Todd Ogasawara) (05/07/91)
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@pinhead.pegasus.com> todd@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@pinhead.pegasus.com Telephone ::: (808) 536-9162 ext. 7
art@pilikia.pegasus.com (Art Neilson) (05/08/91)
In article <1991May06.235754.29292@pinhead.pegasus.com> todd@pinhead.pegasus.com (Todd Ogasawara) writes: >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@pinhead.pegasus.com> todd@pinhead.pegasus.com (Todd Ogasawara) writes: >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? Your problem most likely is caused by structure padding. The following quote from "C A Reference Manual" Second Edition by Harbison and Steele is quite clear on the subject. "The size of an object of a structure type is the amount of storage necessary to represent all components of that type, including any unused padding space between or after the components. The rule is that the structure will be padded out to the size the type would occupy as an element of an array of such types. (For any type T, including structures, the size of an n-element array of T is the same as the size of T times n.) Another way of saying this is that the structure must terminate on the same alignment boundary on which it started; that is, if the structure must begin on an even byte boundary, it must also end on an even byte boundary." The text in the book goes on for several paragraphs more, providing examples and such. See page 107, section 5.6.7 titled "Sizes of Structures" for the complete story. -- Arthur W. Neilson III | INET: art@pilikia.pegasus.com Bank of Hawaii Tech Support | UUCP: uunet!ucsd!nosc!pilikia!art