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