Subject: bin/8880: Output from pac not always formatted correctly.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <bstark@uswest.net>
List: netbsd-bugs
Date: 11/26/1999 00:18:48
>Number:         8880
>Category:       bin
>Synopsis:       Output from pac not always formatted correctly.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Nov 26 00:18:00 1999
>Last-Modified:
>Originator:     Brian Stark
>Organization:

Brian Stark
bstark@uswest.net
>Release:        NetBSD 1.4.1
>Environment:
	
System: NetBSD callisto.niangua.net 1.4.1 NetBSD 1.4.1 (CALLISTO) #5: Sat Nov 6 00:20:51 CST 1999 bstark@callisto.niangua.net:/usr/src/sys/arch/i386/compile/CALLISTO i386


>Description:
	Output from pac not always formatted correctly.

>How-To-Repeat:

  While processing the printer accounting file pac attempts to limit the
  size of the hostname and user name field to 24 characters. However,
  printf() on NetBSD does not limit the size of the field to the size
  specified if the string exceeds this value (see man page for printf
  on a NetBSD 1.4.1 system).

  (NOTE: My copy of 'POSIX Programmer's Guide' from O'Reilly & Associates
  in the section for printf() states that the meaning of the width
  string for the "s" format character will be the maximum number of
  characters to be written. Why doesn't NetBSD's implementation of
  printf follow this??) 

  This presents a formatting problem on systems where the length of the
  hostname and user name fields exceed the 24 character limit that pac
  tries to impose. In file pac.c, functon dumpit(), the following code
  segment exists:
  
        printf("  Login               pages/feet   runs    price\n"); 
        feet = 0.0;
        runs = 0;
        for (ap = base, c = hcount; c--; ap++) {
                hp = *ap;
                runs += hp->h_count;
                feet += hp->h_feetpages;
                printf("%-24s %7.2f %4d   $%6.2f\n", hp->h_name,
                    hp->h_feetpages, hp->h_count, hp->h_feetpages * price);
        }
        if (allflag) {
                printf("\n");  
                printf("%-24s %7.2f %4d   $%6.2f\n", "total", feet,
                    runs, feet * price);
        }
       
  Here is an example using hostname 'callisto.niangua.net' and user
  names 'bstark' and 'root'. This example will show summary information
  for all entries in the accounting file:

  # pac -Pljet4
    Login               pages/feet   runs    price
  callisto.niangua.net:bstark   70.00   26   $  1.40
  callisto.niangua.net:root   21.00   12   $  0.42

  total                      91.00   38   $  1.82
  #

  Here is another example using the same hostname and a specific user,
  'bstark': 
  
  # pac -Pljet4 callisto.niangua.net:bstark
    Login               pages/feet   runs    price
  callisto.niangua.net:bstark   70.00   26   $  1.40
  #  



>Fix:

  I see several possible solutions for this problem. First, the functionality
  of printf could be modified so that if a width is specified for a string
  that will be the maximum number of characters to be printed. A second
  solution would be to change the formatting of the output to avoid this
  problem.

  IMHO, both of these solutions should be implemented. It would be really
  nice if printf worked according to how a POSIX system should work, and
  even if printf did correctly limit the characters printed, it would
  be nice to see full information for the hostname and user (as opposed
  to truncated information). To solve the second solution, the code in
  dumpit could be changed to the following:
  
        printf("pages/feet runs price   host name and/or login\n");
        printf("---------- ---- ------- ----------------------\n");
        feet = 0.0;
        runs = 0;
        for (ap = base, c = hcount; c--; ap++) {
                hp = *ap;
                runs += hp->h_count;
                feet += hp->h_feetpages;
                printf("   %7.2f %4d $%6.2f %-s\n",
                    hp->h_feetpages, hp->h_count, hp->h_feetpages * price,
                    hp->h_name);
        }
        if (allflag) {
                printf("\n");
                printf("   %7.2f %4d $%6.2f total\n",feet,runs,feet * price);
        }
  
  Using the above section of code, the output would now look like this:
  
  callisto:{root}#  ./pac -Pljet4
  pages/feet runs price   host name and/or login
  ---------- ---- ------- ----------------------
       71.00   27 $  1.42 callisto.niangua.net:bstark
        1.00    1 $  0.02 callisto.niangua.net:root
  
       72.00   28 $  1.44 total
  callisto:{root}#  ./pac -Pljet4 callisto.niangua.net:bstark
  pages/feet runs price   host name and/or login
  ---------- ---- ------- ----------------------
       71.00   27 $  1.42 callisto.niangua.net:bstark
  callisto:{root}#
  
NOTE #1: The pac command takes a "-s" parameter that causes it to write
information to a summary file. The format of the data written to this
file looks ok because the data fields are separated by a tab character
and the hostname/login name field is written as a complete string.
  
NOTE #2: There still could be formatting problems if the number of
pages is large and the price per page is large. The maximum dollar
amount that can be shown without formatting problems is $999.99.
However, this is something that can be addressed later...

  
Diff for my changes:
  
callisto:{root}# ident  pac.c.netbsd141
pac.c.netbsd141:
     $NetBSD: pac.c,v 1.10 1997/10/05 15:12:25 mrg Exp $
     $NetBSD: pac.c,v 1.10 1997/10/05 15:12:25 mrg Exp $
callisto:{root}# diff pac.c pac.c.netbsd141
269,270c269
<         printf("pages/feet runs price   host name and/or login\n");
<         printf("---------- ---- ------- ----------------------\n");
---
>       printf("  Login               pages/feet   runs    price\n");
277,279c276,277
<               printf("   %7.2f %4d $%6.2f %-s\n",
<                   hp->h_feetpages, hp->h_count, hp->h_feetpages * price,
<                     hp->h_name);
---
>               printf("%-24s %7.2f %4d   $%6.2f\n", hp->h_name,
>                   hp->h_feetpages, hp->h_count, hp->h_feetpages * price);
283c281,282
<                 printf("   %7.2f %4d $%6.2f total\n",feet,runs,feet * price);
---
>               printf("%-24s %7.2f %4d   $%6.2f\n", "total", feet,
>                   runs, feet * price);


>Audit-Trail:
>Unformatted: