procexec/acct_v3_view.c

This is procexec/acct_v3_view.c, an example to accompany the book, The Linux Programming Interface.

This file is not printed in the book; it is a supplementary file for Chapter 28.

The source code file is copyright 2022, Michael Kerrisk, and is licensed under the GNU General Public License, version 3.

In the listing below, the names of Linux system calls and C library functions are hyperlinked to manual pages from the Linux man-pages project, and the names of functions implemented in the book are hyperlinked to the implementations of those functions.

 

Download procexec/acct_v3_view.c

  Cover of The Linux Programming Interface

Function list (Bold in this list means a function is not static)

/* acct_v3_view.c

   Display contents of a Linux-specific Version 3 process accounting file.

   This program will produce sensible results only when used to read
   an account file produced on a Linux 2.6 (or later) system configured
   with CONFIG_BSD_PROCESS_ACCT_V3.

   See also acct_view.c.

   This program is Linux-specific. The Version 3 accounting file is
   supported since kernel 2.6.8.
*/
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/acct.h>
#include <limits.h>
#include "ugid_functions.h"             /* Declaration of userNameFromId() */
#include "tlpi_hdr.h"

#define TIME_BUF_SIZE 100

#define GLIBC_DEFINES_ACCT_V3           /* This is true since glibc 2.6 */

#ifndef GLIBC_DEFINES_ACCT_V3
struct acct_v3
{
    char        ac_flag;
    char        ac_version;
    u_int16_t   ac_tty;
    u_int32_t   ac_exitcode;
    u_int32_t   ac_uid;
    u_int32_t   ac_gid;
    u_int32_t   ac_pid;
    u_int32_t   ac_ppid;
    u_int32_t   ac_btime;
    float       ac_etime;
    comp_t      ac_utime;
    comp_t      ac_stime;
    comp_t      ac_mem;
    comp_t      ac_io;
    comp_t      ac_rw;
    comp_t      ac_minflt;
    comp_t      ac_majflt;
    comp_t      ac_swaps;
    char        ac_comm[ACCT_COMM];
};

#endif
static long long                /* Convert comp_t value into long long */
comptToLL(comp_t ct)
{
    const int EXP_SIZE = 3;             /* 3-bit, base-8 exponent */
    const int MANTISSA_SIZE = 13;       /* Followed by 13-bit mantissa */
    const int MANTISSA_MASK = (1 << MANTISSA_SIZE) - 1;
    long long mantissa, exp;

    mantissa = ct & MANTISSA_MASK;
    exp = (ct >> MANTISSA_SIZE) & ((1 << EXP_SIZE) - 1);
    return mantissa << (exp * 3);       /* Power of 8 = left shift 3 bits */
}
int
main(int argc, char *argv[])
{
    if (argc != 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s file\n", argv[0]);

    int acctFile = open(argv[1], O_RDONLY);
    if (acctFile == -1)
        errExit("open");

    printf("ver. command    flags   term.   PID   PPID  user     group"
           "      start date+time     CPU   elapsed\n");
    printf("                       status                             "
           "                          time    time\n");

    ssize_t numRead;
    struct acct_v3 ac;
    while ((numRead = read(acctFile, &ac, sizeof(struct acct_v3))) > 0) {
        if (numRead != sizeof(struct acct_v3))
            fatal("partial read");

        printf("%1d    ", (int) ac.ac_version);
        printf("%-8.8s   ", ac.ac_comm);

        printf("%c", (ac.ac_flag & AFORK) ? 'F' : '-') ;
        printf("%c", (ac.ac_flag & ASU)   ? 'S' : '-') ;
        printf("%c", (ac.ac_flag & AXSIG) ? 'X' : '-') ;
        printf("%c", (ac.ac_flag & ACORE) ? 'C' : '-') ;

        printf(" %#6lx   ", (unsigned long) ac.ac_exitcode);

        printf(" %5ld %5ld  ", (long) ac.ac_pid, (long) ac.ac_ppid);

        char *s;
        s = userNameFromId(ac.ac_uid);
        printf("%-8.8s ", (s == NULL) ? "???" : s);

        s = groupNameFromId(ac.ac_gid);
        printf("%-8.8s ", (s == NULL) ? "???" : s);

        time_t t = ac.ac_btime;
        struct tm *loc = localtime(&t);
        if (loc == NULL) {
            printf("???Unknown time???  ");
        } else {
            char timeBuf[TIME_BUF_SIZE];
            strftime(timeBuf, TIME_BUF_SIZE, "%Y-%m-%d %T ", loc);
            printf("%s ", timeBuf);
        }

        printf("%5.2f %7.2f ", (double) (comptToLL(ac.ac_utime) +
                    comptToLL(ac.ac_stime)) / sysconf(_SC_CLK_TCK),
                ac.ac_etime / sysconf(_SC_CLK_TCK));
        printf("\n");
    }

    if (numRead == -1)
        errExit("read");

    exit(EXIT_SUCCESS);
}

 

Download procexec/acct_v3_view.c

Note that, in most cases, the programs rendered in these web pages are not free standing: you'll typically also need a few other source files (mostly in the lib/ subdirectory) as well. Generally, it's easier to just download the entire source tarball and build the programs with make(1). By hovering your mouse over the various hyperlinked include files and function calls above, you can see which other source files this file depends on.

Valid XHTML 1.1