"Fossies" - the Fresh Open Source Software Archive

Member "atop-2.8.1/parseable.c" (7 Jan 2023, 23454 Bytes) of package /linux/misc/atop-2.8.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "parseable.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.7.1_vs_2.8.0.

    1 /*
    2 ** ATOP - System & Process Monitor
    3 **
    4 ** The program 'atop' offers the possibility to view the activity of
    5 ** the system on system-level as well as process-level.
    6 **
    7 ** ==========================================================================
    8 ** Author:      Gerlof Langeveld
    9 ** E-mail:      gerlof.langeveld@atoptool.nl
   10 ** Date:        February 2007
   11 ** --------------------------------------------------------------------------
   12 ** Copyright (C) 2007-2021 Gerlof Langeveld
   13 **
   14 ** This program is free software; you can redistribute it and/or modify it
   15 ** under the terms of the GNU General Public License as published by the
   16 ** Free Software Foundation; either version 2, or (at your option) any
   17 ** later version.
   18 **
   19 ** This program is distributed in the hope that it will be useful, but
   20 ** WITHOUT ANY WARRANTY; without even the implied warranty of
   21 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   22 ** See the GNU General Public License for more details.
   23 **
   24 ** You should have received a copy of the GNU General Public License
   25 ** along with this program; if not, write to the Free Software
   26 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27 ** --------------------------------------------------------------------------
   28 */
   29 #include <sys/types.h>
   30 #include <stdio.h>
   31 #include <unistd.h>
   32 #include <stdlib.h>
   33 #include <string.h>
   34 #include <limits.h>
   35 #include <sys/utsname.h>
   36 
   37 #include "atop.h"
   38 #include "photosyst.h"
   39 #include "photoproc.h"
   40 #include "parseable.h"
   41 
   42 void    print_CPU();
   43 void    print_cpu();
   44 void    print_CPL();
   45 void    print_GPU();
   46 void    print_MEM();
   47 void    print_SWP();
   48 void    print_PAG();
   49 void    print_PSI();
   50 void    print_LVM();
   51 void    print_MDD();
   52 void    print_DSK();
   53 void    print_NFM();
   54 void    print_NFC();
   55 void    print_NFS();
   56 void    print_NET();
   57 void    print_IFB();
   58 void    print_NUM();
   59 void    print_NUC();
   60 void    print_LLC();
   61 
   62 void    print_PRG();
   63 void    print_PRC();
   64 void    print_PRM();
   65 void    print_PRD();
   66 void    print_PRN();
   67 void    print_PRE();
   68 
   69 static char *spaceformat(char *, char *);
   70 static int  cgroupv2max(int, int);
   71 
   72 /*
   73 ** table with possible labels and the corresponding
   74 ** print-function for parseable output
   75 */
   76 struct labeldef {
   77     char    *label;
   78     int valid;
   79     void    (*prifunc)(char *, struct sstat *, struct tstat *, int);
   80 };
   81 
   82 static struct labeldef  labeldef[] = {
   83     { "CPU",    0,  print_CPU },
   84     { "cpu",    0,  print_cpu },
   85     { "CPL",    0,  print_CPL },
   86     { "GPU",    0,  print_GPU },
   87     { "MEM",    0,  print_MEM },
   88     { "SWP",    0,  print_SWP },
   89     { "PAG",    0,  print_PAG },
   90     { "PSI",    0,  print_PSI },
   91     { "LVM",    0,  print_LVM },
   92     { "MDD",    0,  print_MDD },
   93     { "DSK",    0,  print_DSK },
   94     { "NFM",    0,  print_NFM },
   95     { "NFC",    0,  print_NFC },
   96     { "NFS",    0,  print_NFS },
   97     { "NET",    0,  print_NET },
   98     { "IFB",    0,  print_IFB },
   99     { "NUM",    0,  print_NUM },
  100     { "NUC",    0,  print_NUC },
  101     { "LLC",    0,  print_LLC },
  102 
  103     { "PRG",    0,  print_PRG },
  104     { "PRC",    0,  print_PRC },
  105     { "PRM",    0,  print_PRM },
  106     { "PRD",    0,  print_PRD },
  107     { "PRN",    0,  print_PRN },
  108     { "PRE",    0,  print_PRE },
  109 };
  110 
  111 static int  numlabels = sizeof labeldef/sizeof(struct labeldef);
  112 
  113 /*
  114 ** analyse the parse-definition string that has been
  115 ** passed as argument with the flag -P
  116 */
  117 int
  118 parsedef(char *pd)
  119 {
  120     register int    i;
  121     char        *p, *ep = pd + strlen(pd);
  122 
  123     /*
  124     ** check if string passed bahind -P is not another flag
  125     */
  126     if (*pd == '-')
  127     {
  128         fprintf(stderr, "flag -P should be followed by label list\n");
  129         return 0;
  130     }
  131 
  132     /*
  133     ** check list of comma-separated labels 
  134     */
  135     while (pd < ep)
  136     {
  137         /*
  138         ** exchange comma by null-byte
  139         */
  140         if ( (p = strchr(pd, ',')) )
  141             *p = 0; 
  142         else
  143             p  = ep-1;
  144 
  145         /*
  146         ** check if the next label exists
  147         */
  148         for (i=0; i < numlabels; i++)
  149         {
  150             if ( strcmp(labeldef[i].label, pd) == 0)
  151             {
  152                 labeldef[i].valid = 1;
  153                 break;
  154             }
  155         }
  156 
  157         /*
  158         ** non-existing label has been used
  159         */
  160         if (i == numlabels)
  161         {
  162             /*
  163             ** check if special label 'ALL' has been used
  164             */
  165             if ( strcmp("ALL", pd) == 0)
  166             {
  167                 for (i=0; i < numlabels; i++)
  168                     labeldef[i].valid = 1;
  169                 break;
  170             }
  171             else
  172             {
  173                 fprintf(stderr, "label %s not found\n", pd);
  174                 return 0;
  175             }
  176         }
  177 
  178         pd = p+1;
  179     }
  180 
  181     setbuf(stdout, (char *)0);
  182 
  183     return 1;
  184 }
  185 
  186 /*
  187 ** produce parseable output for an interval
  188 */
  189 char
  190 parseout(time_t curtime, int numsecs,
  191          struct devtstat *devtstat, struct sstat *sstat,
  192          int nexit, unsigned int noverflow, char flag)
  193 {
  194     register int    i;
  195     char        datestr[32], timestr[32], header[256];
  196 
  197     /*
  198     ** print reset-label for sample-values since boot
  199     */
  200     if (flag&RRBOOT)
  201         printf("RESET\n");
  202 
  203     /*
  204     ** search all labels which are selected before
  205     */
  206     for (i=0; i < numlabels; i++)
  207     {
  208         if (labeldef[i].valid)
  209         {
  210             /*
  211             ** prepare generic columns
  212             */
  213             convdate(curtime, datestr);
  214             convtime(curtime, timestr);
  215 
  216             snprintf(header, sizeof header, "%s %s %ld %s %s %d",
  217                 labeldef[i].label,
  218                 utsname.nodename,
  219                 curtime,
  220                 datestr, timestr, numsecs);
  221 
  222             /*
  223             ** call a selected print-function
  224             */
  225             (labeldef[i].prifunc)(header, sstat,
  226                 devtstat->taskall, devtstat->ntaskall);
  227         }
  228     }
  229 
  230     /*
  231     ** print separator
  232     */
  233     printf("SEP\n");
  234 
  235     return '\0';
  236 }
  237 
  238 /*
  239 ** print functions for system-level statistics
  240 */
  241 void
  242 calc_freqscale(count_t maxfreq, count_t cnt, count_t ticks, 
  243                count_t *freq, int *freqperc)
  244 {
  245         // if ticks != 0, do full calcs
  246         if (maxfreq && ticks) 
  247         {
  248             *freq=cnt/ticks;
  249             *freqperc=100* *freq / maxfreq;
  250         } 
  251         else if (maxfreq)   // max frequency is known so % can be calculated
  252         {
  253             *freq=cnt;
  254             *freqperc=100*cnt/maxfreq;
  255         }
  256         else if (cnt)       // no max known, set % to 100
  257         {
  258             *freq=cnt;
  259             *freqperc=100;
  260         }
  261         else                // nothing is known: set freq to 0, % to 100
  262         {
  263             *freq=0;
  264             *freqperc=100;
  265         }
  266 }
  267 
  268 
  269 void
  270 print_CPU(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  271 {
  272         count_t maxfreq=0;
  273         count_t cnt=0;
  274         count_t ticks=0;
  275         count_t freq;
  276         int freqperc;
  277         int i;
  278 
  279         // calculate average clock frequency
  280     for (i=0; i < ss->cpu.nrcpu; i++)
  281         {
  282                 cnt    += ss->cpu.cpu[i].freqcnt.cnt;
  283                 ticks  += ss->cpu.cpu[i].freqcnt.ticks;
  284         }
  285         maxfreq = ss->cpu.cpu[0].freqcnt.maxfreq;
  286         calc_freqscale(maxfreq, cnt, ticks, &freq, &freqperc);
  287 
  288     if (ss->cpu.all.instr == 1)
  289     {
  290             ss->cpu.all.instr = 0;
  291             ss->cpu.all.cycle = 0;
  292     }
  293 
  294     printf("%s %u %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %d %lld %lld\n",
  295             hp,
  296             hertz,
  297                 ss->cpu.nrcpu,
  298                 ss->cpu.all.stime,
  299                 ss->cpu.all.utime,
  300                 ss->cpu.all.ntime,
  301                 ss->cpu.all.itime,
  302                 ss->cpu.all.wtime,
  303                 ss->cpu.all.Itime,
  304                 ss->cpu.all.Stime,
  305                 ss->cpu.all.steal,
  306                 ss->cpu.all.guest,
  307                         freq,
  308                         freqperc,
  309                 ss->cpu.all.instr,
  310                 ss->cpu.all.cycle
  311                         );
  312 }
  313 
  314 void
  315 print_cpu(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  316 {
  317     register int i;
  318         count_t maxfreq=0;
  319         count_t cnt=0;
  320         count_t ticks=0;
  321         count_t freq;
  322         int freqperc;
  323 
  324     for (i=0; i < ss->cpu.nrcpu; i++)
  325     {
  326                 cnt    = ss->cpu.cpu[i].freqcnt.cnt;
  327                 ticks  = ss->cpu.cpu[i].freqcnt.ticks;
  328                 maxfreq= ss->cpu.cpu[0].freqcnt.maxfreq;
  329 
  330                 calc_freqscale(maxfreq, cnt, ticks, &freq, &freqperc);
  331 
  332         printf("%s %u %d %lld %lld %lld "
  333                "%lld %lld %lld %lld %lld %lld %lld %d %lld %lld\n",
  334             hp, hertz, i,
  335                 ss->cpu.cpu[i].stime,
  336                 ss->cpu.cpu[i].utime,
  337                 ss->cpu.cpu[i].ntime,
  338                 ss->cpu.cpu[i].itime,
  339                 ss->cpu.cpu[i].wtime,
  340                 ss->cpu.cpu[i].Itime,
  341                 ss->cpu.cpu[i].Stime,
  342                 ss->cpu.cpu[i].steal,
  343                 ss->cpu.cpu[i].guest,
  344                         freq,
  345                         freqperc,
  346                 ss->cpu.cpu[i].instr,
  347                 ss->cpu.cpu[i].cycle
  348             );
  349     }
  350 }
  351 
  352 void
  353 print_CPL(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  354 {
  355     printf("%s %lld %.2f %.2f %.2f %lld %lld\n",
  356             hp,
  357                 ss->cpu.nrcpu,
  358                 ss->cpu.lavg1,
  359                 ss->cpu.lavg5,
  360                 ss->cpu.lavg15,
  361                 ss->cpu.csw,
  362                 ss->cpu.devint);
  363 }
  364 
  365 void
  366 print_GPU(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  367 {
  368     int i;
  369 
  370     for (i=0; i < ss->gpu.nrgpus; i++)
  371     {
  372         printf("%s %d %s %s %d %d %lld %lld %lld %lld %lld %lld\n",
  373             hp, i,
  374                 ss->gpu.gpu[i].busid,
  375                 ss->gpu.gpu[i].type,
  376                 ss->gpu.gpu[i].gpupercnow,
  377                 ss->gpu.gpu[i].mempercnow,
  378                 ss->gpu.gpu[i].memtotnow,
  379                 ss->gpu.gpu[i].memusenow,
  380                 ss->gpu.gpu[i].samples,
  381                 ss->gpu.gpu[i].gpuperccum,
  382                 ss->gpu.gpu[i].memperccum,
  383                 ss->gpu.gpu[i].memusecum);
  384     }
  385 }
  386 
  387 void
  388 print_MEM(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  389 {
  390     printf( "%s %u %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld "
  391         "%lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
  392             hp,
  393             pagesize,
  394             ss->mem.physmem,
  395             ss->mem.freemem,
  396             ss->mem.cachemem,
  397             ss->mem.buffermem,
  398             ss->mem.slabmem,
  399             ss->mem.cachedrt,
  400             ss->mem.slabreclaim,
  401                 ss->mem.vmwballoon != -1 ? ss->mem.vmwballoon : 0,
  402                 ss->mem.shmem,
  403                 ss->mem.shmrss,
  404                 ss->mem.shmswp,
  405                 ss->mem.hugepagesz,
  406                 ss->mem.tothugepage,
  407                 ss->mem.freehugepage,
  408                 ss->mem.zfsarcsize != -1 ? ss->mem.zfsarcsize : 0,
  409                 ss->mem.ksmsharing != -1 ? ss->mem.ksmsharing : 0,
  410                 ss->mem.ksmshared  != -1 ? ss->mem.ksmshared  : 0,
  411             ss->mem.tcpsock,
  412             ss->mem.udpsock,
  413             ss->mem.pagetables);
  414 }
  415 
  416 void
  417 print_SWP(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  418 {
  419     printf( "%s %u %lld %lld %lld %lld %lld %lld %lld %lld\n",
  420             hp,
  421             pagesize,
  422             ss->mem.totswap,
  423             ss->mem.freeswap,
  424             ss->mem.swapcached,
  425             ss->mem.committed,
  426             ss->mem.commitlim,
  427                 ss->mem.swapcached,
  428                 ss->mem.zswstored != -1 ? ss->mem.zswstored : 0,
  429                 ss->mem.zswtotpool != -1 ? ss->mem.zswtotpool : 0);
  430 }
  431 
  432 void
  433 print_PAG(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  434 {
  435     printf("%s %u %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
  436             hp,
  437             pagesize,
  438             ss->mem.pgscans,
  439             ss->mem.allocstall,
  440             (long long)0,
  441             ss->mem.swins,
  442             ss->mem.swouts,
  443             ss->mem.oomkills,
  444             ss->mem.compactstall,
  445             ss->mem.pgmigrate,
  446             ss->mem.numamigrate,
  447             ss->mem.pgins,
  448             ss->mem.pgouts);
  449 }
  450 
  451 void
  452 print_PSI(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  453 {
  454     printf("%s %c %.1f %.1f %.1f %llu %.1f %.1f %.1f %llu "
  455            "%.1f %.1f %.1f %llu %.1f %.1f %.1f %llu %.1f %.1f %.1f %llu\n",
  456         hp, ss->psi.present ? 'y' : 'n',
  457                 ss->psi.cpusome.avg10, ss->psi.cpusome.avg60,
  458                 ss->psi.cpusome.avg300, ss->psi.cpusome.total,
  459                 ss->psi.memsome.avg10, ss->psi.memsome.avg60,
  460                 ss->psi.memsome.avg300, ss->psi.memsome.total,
  461                 ss->psi.memfull.avg10, ss->psi.memfull.avg60,
  462                 ss->psi.memfull.avg300, ss->psi.memfull.total,
  463                 ss->psi.iosome.avg10, ss->psi.iosome.avg60,
  464                 ss->psi.iosome.avg300, ss->psi.iosome.total,
  465                 ss->psi.iofull.avg10, ss->psi.iofull.avg60,
  466                 ss->psi.iofull.avg300, ss->psi.iofull.total);
  467 }
  468 
  469 void
  470 print_LVM(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  471 {
  472     register int    i;
  473 
  474         for (i=0; ss->dsk.lvm[i].name[0]; i++)
  475     {
  476         printf( "%s %s %lld %lld %lld %lld %lld %lld %lld %lld %.2f\n",
  477             hp,
  478             ss->dsk.lvm[i].name,
  479             ss->dsk.lvm[i].io_ms,
  480             ss->dsk.lvm[i].nread,
  481             ss->dsk.lvm[i].nrsect,
  482             ss->dsk.lvm[i].nwrite,
  483             ss->dsk.lvm[i].nwsect,
  484             ss->dsk.lvm[i].ndisc,
  485             ss->dsk.lvm[i].ndsect,
  486             ss->dsk.lvm[i].inflight,
  487             ss->dsk.lvm[i].io_ms > 0 ?
  488               (double)ss->dsk.lvm[i].avque/ss->dsk.lvm[i].io_ms :
  489               0.0);
  490     }
  491 }
  492 
  493 void
  494 print_MDD(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  495 {
  496     register int    i;
  497 
  498         for (i=0; ss->dsk.mdd[i].name[0]; i++)
  499     {
  500         printf( "%s %s %lld %lld %lld %lld %lld %lld %lld %lld %.2f\n",
  501             hp,
  502             ss->dsk.mdd[i].name,
  503             ss->dsk.mdd[i].io_ms,
  504             ss->dsk.mdd[i].nread,
  505             ss->dsk.mdd[i].nrsect,
  506             ss->dsk.mdd[i].nwrite,
  507             ss->dsk.mdd[i].nwsect,
  508             ss->dsk.mdd[i].ndisc,
  509             ss->dsk.mdd[i].ndsect,
  510             ss->dsk.mdd[i].inflight,
  511             ss->dsk.mdd[i].io_ms > 0 ?
  512               (double)ss->dsk.mdd[i].avque/ss->dsk.mdd[i].io_ms :
  513               0.0);
  514     }
  515 }
  516 
  517 void
  518 print_DSK(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  519 {
  520     register int    i;
  521 
  522         for (i=0; ss->dsk.dsk[i].name[0]; i++)
  523     {
  524         printf( "%s %s %lld %lld %lld %lld %lld %lld %lld %lld %.2f\n",
  525             hp,
  526             ss->dsk.dsk[i].name,
  527             ss->dsk.dsk[i].io_ms,
  528             ss->dsk.dsk[i].nread,
  529             ss->dsk.dsk[i].nrsect,
  530             ss->dsk.dsk[i].nwrite,
  531             ss->dsk.dsk[i].nwsect,
  532             ss->dsk.dsk[i].ndisc,
  533             ss->dsk.dsk[i].ndsect,
  534             ss->dsk.dsk[i].inflight,
  535             ss->dsk.dsk[i].io_ms > 0 ?
  536               (double)ss->dsk.dsk[i].avque/ss->dsk.dsk[i].io_ms :
  537               0.0);
  538     }
  539 }
  540 
  541 void
  542 print_NFM(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  543 {
  544     register int    i;
  545 
  546         for (i=0; i < ss->nfs.nfsmounts.nrmounts; i++)
  547     {
  548         printf("%s %s %lld %lld %lld %lld %lld %lld %lld %lld\n",
  549             hp,
  550             ss->nfs.nfsmounts.nfsmnt[i].mountdev,
  551             ss->nfs.nfsmounts.nfsmnt[i].bytestotread,
  552             ss->nfs.nfsmounts.nfsmnt[i].bytestotwrite,
  553             ss->nfs.nfsmounts.nfsmnt[i].bytesread,
  554             ss->nfs.nfsmounts.nfsmnt[i].byteswrite,
  555             ss->nfs.nfsmounts.nfsmnt[i].bytesdread,
  556             ss->nfs.nfsmounts.nfsmnt[i].bytesdwrite,
  557             ss->nfs.nfsmounts.nfsmnt[i].pagesmread,
  558             ss->nfs.nfsmounts.nfsmnt[i].pagesmwrite);
  559     }
  560 }
  561 
  562 void
  563 print_NFC(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  564 {
  565     printf( "%s %lld %lld %lld %lld %lld\n",
  566             hp,
  567             ss->nfs.client.rpccnt,
  568             ss->nfs.client.rpcread,
  569             ss->nfs.client.rpcwrite,
  570             ss->nfs.client.rpcretrans,
  571             ss->nfs.client.rpcautrefresh);
  572 }
  573 
  574 void
  575 print_NFS(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  576 {
  577     printf( "%s %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld "
  578             "%lld %lld %lld %lld %lld\n",
  579             hp,
  580             ss->nfs.server.rpccnt,
  581             ss->nfs.server.rpcread,
  582             ss->nfs.server.rpcwrite,
  583             ss->nfs.server.nrbytes,
  584             ss->nfs.server.nwbytes,
  585             ss->nfs.server.rpcbadfmt,
  586             ss->nfs.server.rpcbadaut,
  587             ss->nfs.server.rpcbadcln,
  588             ss->nfs.server.netcnt,
  589             ss->nfs.server.nettcpcnt,
  590             ss->nfs.server.netudpcnt,
  591             ss->nfs.server.nettcpcon,
  592             ss->nfs.server.rchits,
  593             ss->nfs.server.rcmiss,
  594             ss->nfs.server.rcnoca);
  595 }
  596 
  597 void
  598 print_NET(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  599 {
  600     register int    i;
  601 
  602     printf( "%s %s %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
  603             hp,
  604             "upper",
  605                 ss->net.tcp.InSegs,
  606                 ss->net.tcp.OutSegs,
  607                 ss->net.udpv4.InDatagrams +
  608                 ss->net.udpv6.Udp6InDatagrams,
  609                 ss->net.udpv4.OutDatagrams +
  610                 ss->net.udpv6.Udp6OutDatagrams,
  611                 ss->net.ipv4.InReceives  +
  612                 ss->net.ipv6.Ip6InReceives,
  613                 ss->net.ipv4.OutRequests +
  614                 ss->net.ipv6.Ip6OutRequests,
  615                 ss->net.ipv4.InDelivers +
  616                     ss->net.ipv6.Ip6InDelivers,
  617                 ss->net.ipv4.ForwDatagrams +
  618                     ss->net.ipv6.Ip6OutForwDatagrams,
  619                 ss->net.udpv4.InErrors +
  620                 ss->net.udpv6.Udp6InErrors,
  621                 ss->net.udpv4.NoPorts +
  622                 ss->net.udpv6.Udp6NoPorts,
  623             ss->net.tcp.ActiveOpens,
  624             ss->net.tcp.PassiveOpens,
  625             ss->net.tcp.CurrEstab,
  626             ss->net.tcp.RetransSegs,
  627             ss->net.tcp.InErrs,
  628             ss->net.tcp.OutRsts);
  629 
  630     for (i=0; ss->intf.intf[i].name[0]; i++)
  631     {
  632         printf( "%s %s %lld %lld %lld %lld %ld %d\n",
  633             hp,
  634             ss->intf.intf[i].name,
  635             ss->intf.intf[i].rpack,
  636             ss->intf.intf[i].rbyte,
  637             ss->intf.intf[i].spack,
  638             ss->intf.intf[i].sbyte,
  639             ss->intf.intf[i].speed,
  640             ss->intf.intf[i].duplex);
  641     }
  642 }
  643 
  644 void
  645 print_IFB(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  646 {
  647     register int    i;
  648 
  649     for (i=0; i < ss->ifb.nrports; i++)
  650     {
  651         printf( "%s %s %hd %hd %lld %lld %lld %lld %lld\n",
  652             hp,
  653             ss->ifb.ifb[i].ibname,
  654             ss->ifb.ifb[i].portnr,
  655             ss->ifb.ifb[i].lanes,
  656             ss->ifb.ifb[i].rate,
  657             ss->ifb.ifb[i].rcvb,
  658             ss->ifb.ifb[i].sndb,
  659             ss->ifb.ifb[i].rcvp,
  660             ss->ifb.ifb[i].sndp);
  661     }
  662 }
  663 
  664 void
  665 print_NUM(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  666 {
  667     register int    i;
  668 
  669     for (i=0; i < ss->memnuma.nrnuma; i++)
  670     {
  671         printf( "%s %d %u %.0f %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
  672             hp, ss->memnuma.numa[i].numanr,
  673             pagesize,
  674             ss->memnuma.numa[i].frag * 100.0,
  675             ss->memnuma.numa[i].totmem,
  676             ss->memnuma.numa[i].freemem,
  677             ss->memnuma.numa[i].active,
  678             ss->memnuma.numa[i].inactive,
  679             ss->memnuma.numa[i].filepage,
  680             ss->memnuma.numa[i].dirtymem,
  681             ss->memnuma.numa[i].slabmem,
  682             ss->memnuma.numa[i].slabreclaim,
  683             ss->memnuma.numa[i].shmem,
  684             ss->memnuma.numa[i].tothp);
  685     }
  686 }
  687 
  688 void
  689 print_NUC(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  690 {
  691     register int    i;
  692 
  693     for (i=0; i < ss->cpunuma.nrnuma; i++)
  694     {
  695         printf( "%s %d %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
  696             hp, ss->cpunuma.numa[i].numanr,
  697                 ss->cpunuma.numa[i].nrcpu,
  698                 ss->cpunuma.numa[i].stime,
  699                 ss->cpunuma.numa[i].utime,
  700                 ss->cpunuma.numa[i].ntime,
  701                 ss->cpunuma.numa[i].itime,
  702                 ss->cpunuma.numa[i].wtime,
  703                 ss->cpunuma.numa[i].Itime,
  704                 ss->cpunuma.numa[i].Stime,
  705                 ss->cpunuma.numa[i].steal,
  706                 ss->cpunuma.numa[i].guest);
  707     }
  708 }
  709 
  710 void
  711 print_LLC(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  712 {
  713     register int    i;
  714 
  715     for (i=0; i < ss->llc.nrllcs; i++)
  716     {
  717         printf( "%s LLC%03d %3.1f%% %lld %lld\n",
  718             hp,
  719             ss->llc.perllc[i].id,
  720             ss->llc.perllc[i].occupancy * 100,
  721             ss->llc.perllc[i].mbm_total,
  722             ss->llc.perllc[i].mbm_local);
  723     }
  724 }
  725 
  726 /*
  727 ** print functions for process-level statistics
  728 */
  729 void
  730 print_PRG(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  731 {
  732     register int    i, exitcode;
  733     char        namout[PNAMLEN+1+2], cmdout[CMDLEN+1+2],
  734             pathout[CGRLEN+1];
  735 
  736     for (i=0; i < nact; i++, ps++)
  737     {
  738         if (ps->gen.excode & 0xff)      // killed by signal?
  739             exitcode = (ps->gen.excode & 0x7f) + 256;
  740         else
  741             exitcode = (ps->gen.excode >>   8) & 0xff;
  742 
  743         printf("%s %d %s %c %d %d %d %d %d %ld %s %d %d %d %d "
  744                "%d %d %d %d %d %d %ld %c %d %d %s %c %s\n",
  745             hp,
  746             ps->gen.pid,
  747             spaceformat(ps->gen.name, namout),
  748             ps->gen.state,
  749             ps->gen.ruid,
  750             ps->gen.rgid,
  751             ps->gen.tgid,
  752             ps->gen.nthr,
  753             exitcode,
  754             ps->gen.btime,
  755             spaceformat(ps->gen.cmdline, cmdout),
  756             ps->gen.ppid,
  757             ps->gen.nthrrun,
  758             ps->gen.nthrslpi,
  759             ps->gen.nthrslpu,
  760             ps->gen.euid,
  761             ps->gen.egid,
  762             ps->gen.suid,
  763             ps->gen.sgid,
  764             ps->gen.fsuid,
  765             ps->gen.fsgid,
  766             ps->gen.elaps,
  767             ps->gen.isproc ? 'y':'n',
  768             ps->gen.vpid,
  769             ps->gen.ctid,
  770             ps->gen.container[0] ? ps->gen.container:"-",
  771                 ps->gen.excode & ~(INT_MAX) ? 'N' : '-',
  772             spaceformat(ps->gen.cgpath, pathout));
  773     }
  774 }
  775 
  776 void
  777 print_PRC(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  778 {
  779     register int    i;
  780     char        namout[PNAMLEN+1+2], wchanout[20];
  781 
  782     for (i=0; i < nact; i++, ps++)
  783     {
  784         printf("%s %d %s %c %u %lld %lld %d %d %d %d %d %d %d %c "
  785                "%llu %s %llu %d %d\n",
  786             hp,
  787             ps->gen.pid,
  788             spaceformat(ps->gen.name, namout),
  789             ps->gen.state,
  790             hertz,
  791             ps->cpu.utime,
  792             ps->cpu.stime,
  793             ps->cpu.nice,
  794             ps->cpu.prio,
  795             ps->cpu.rtprio,
  796             ps->cpu.policy,
  797             ps->cpu.curcpu,
  798             ps->cpu.sleepavg,
  799             ps->gen.tgid,
  800             ps->gen.isproc ? 'y':'n',
  801             ps->cpu.rundelay,
  802             spaceformat(ps->cpu.wchan, wchanout),
  803             ps->cpu.blkdelay,
  804             cgroupv2max(ps->gen.isproc, ps->cpu.cgcpumax),
  805             cgroupv2max(ps->gen.isproc, ps->cpu.cgcpumaxr));
  806     }
  807 }
  808 
  809 void
  810 print_PRM(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  811 {
  812     register int    i;
  813     char        namout[PNAMLEN+1+2];
  814 
  815     for (i=0; i < nact; i++, ps++)
  816     {
  817         printf("%s %d %s %c %u %lld %lld %lld %lld %lld %lld "
  818                "%lld %lld %lld %lld %lld %d %c %lld %lld %d %d %d %d\n",
  819             hp,
  820             ps->gen.pid,
  821             spaceformat(ps->gen.name, namout),
  822             ps->gen.state,
  823             pagesize,
  824             ps->mem.vmem,
  825             ps->mem.rmem,
  826             ps->mem.vexec,
  827             ps->mem.vgrow,
  828             ps->mem.rgrow,
  829             ps->mem.minflt,
  830             ps->mem.majflt,
  831             ps->mem.vlibs,
  832             ps->mem.vdata,
  833             ps->mem.vstack,
  834             ps->mem.vswap,
  835             ps->gen.tgid,
  836             ps->gen.isproc ? 'y':'n',
  837             ps->mem.pmem == (unsigned long long)-1LL ?
  838                             0:ps->mem.pmem,
  839             ps->mem.vlock,
  840             cgroupv2max(ps->gen.isproc, ps->mem.cgmemmax),
  841             cgroupv2max(ps->gen.isproc, ps->mem.cgmemmaxr),
  842             cgroupv2max(ps->gen.isproc, ps->mem.cgswpmax),
  843             cgroupv2max(ps->gen.isproc, ps->mem.cgswpmaxr));
  844     }
  845 }
  846 
  847 void
  848 print_PRD(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  849 {
  850     register int    i;
  851     char        namout[PNAMLEN+1+2];
  852 
  853     for (i=0; i < nact; i++, ps++)
  854     {
  855         printf("%s %d %s %c %c %c %lld %lld %lld %lld %lld %d n %c\n",
  856             hp,
  857             ps->gen.pid,
  858             spaceformat(ps->gen.name, namout),
  859             ps->gen.state,
  860             'n',
  861             supportflags & IOSTAT ? 'y' : 'n',
  862             ps->dsk.rio, ps->dsk.rsz,
  863             ps->dsk.wio, ps->dsk.wsz, ps->dsk.cwsz,
  864             ps->gen.tgid,
  865             ps->gen.isproc ? 'y':'n');
  866     }
  867 }
  868 
  869 void
  870 print_PRN(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  871 {
  872     register int    i;
  873     char        namout[PNAMLEN+1+2];
  874 
  875     for (i=0; i < nact; i++, ps++)
  876     {
  877         printf("%s %d %s %c %c %lld %lld %lld %lld %lld %lld "
  878                "%lld %lld %d %d %d %c\n",
  879             hp,
  880             ps->gen.pid,
  881             spaceformat(ps->gen.name, namout),
  882             ps->gen.state,
  883             supportflags & NETATOP ? 'y' : 'n',
  884             ps->net.tcpsnd, ps->net.tcpssz,
  885             ps->net.tcprcv, ps->net.tcprsz,
  886             ps->net.udpsnd, ps->net.udpssz,
  887             ps->net.udprcv, ps->net.udprsz,
  888             0,              0,
  889             ps->gen.tgid,   ps->gen.isproc ? 'y':'n');
  890     }
  891 }
  892 
  893 void
  894 print_PRE(char *hp, struct sstat *ss, struct tstat *ps, int nact)
  895 {
  896     register int    i;
  897     char        namout[PNAMLEN+1+2];
  898 
  899     for (i=0; i < nact; i++, ps++)
  900     {
  901         printf("%s %d %s %c %c %d %x %d %d %lld %lld %lld\n",
  902             hp,
  903             ps->gen.pid,
  904             spaceformat(ps->gen.name, namout),
  905             ps->gen.state,
  906             ps->gpu.state == '\0' ? 'N':ps->gpu.state,
  907             ps->gpu.nrgpus,
  908             ps->gpu.gpulist,
  909             ps->gpu.gpubusy,
  910             ps->gpu.membusy,
  911             ps->gpu.memnow,
  912             ps->gpu.memcum,
  913             ps->gpu.sample);
  914     }
  915 }
  916 
  917 
  918 /*
  919 ** Strings, like command name, might contain spaces
  920 ** and will be represented for that reason surrounded
  921 ** by parenthesis. However, this is difficult to parse
  922 ** by other tools, so the option -Z might have been
  923 ** specified to exchange all spaces by underscores while
  924 ** omitting the parenthesis in that case.
  925 **
  926 ** This function formats the input string (istr) in the
  927 ** required format to the output string (ostr).
  928 ** Take care that the buffer pointed to by ostr is at least
  929 ** two bytes larger than the input string (for the parenthesis).
  930 ** The pointer ostr is also returned.
  931 */
  932 static char *
  933 spaceformat(char *istr, char *ostr)
  934 {
  935     // formatting with spaces and parenthesis required?
  936     if (!rmspaces)
  937     {
  938         *ostr = '(';
  939         strcpy(ostr+1, istr);
  940         strcat(ostr, ")");
  941     }
  942     // formatting with underscores without parenthesis required
  943     else
  944     {
  945         register char *pi = istr, *po = ostr;
  946 
  947         while (*pi)
  948         {
  949             if (*pi == ' ')
  950             {
  951                 *po++ = '_';
  952                 pi++;
  953             }
  954             else
  955             {
  956                 *po++ = *pi++;
  957             }
  958         }
  959 
  960         if (po == ostr)     // empty string: still return underscore
  961             *po++ = '_';
  962 
  963         *po = '\0';     // terminate output string
  964     }
  965 
  966     return ostr;
  967 }
  968 
  969 /*
  970 ** return proper integer for cgroup v2 maximum values
  971 */
  972 static int
  973 cgroupv2max(int isproc, int max)
  974 {
  975     if (! (supportflags&CGROUPV2))
  976         return -3;
  977 
  978     if (! isproc)
  979         return -2;
  980 
  981     return max;
  982 }