📄 output.c
字号:
/* * Copyright 1999 by Albert Cahalan; all rights resered. * * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version * at your option, as published by the Free Software Foundation. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. *//* * This file is really gross, and I know it. I looked into several * alternate ways to deal with the mess, and they were all ugly. * * FreeBSD has a fancy hack using offsets into a struct -- that * saves code but it is _really_ gross. See the PO macro below. * * We could have a second column width for wide output format. * For example, Digital prints the real-time signals. *//* * Data table idea: * * table 1 maps aix to specifier * table 2 maps shortsort to specifier * table 3 maps macro to specifiers * table 4 maps specifier to title,datatype,offset,vendor,helptext * table 5 maps datatype to justification,width,widewidth,sorting,printing * * Here, "datatype" could be user,uid,u16,pages,deltaT,signals,tty,longtty... * It must be enough to determine printing and sorting. * * After the tables, increase width as needed to fit the header. * * Table 5 could go in a file with the output functions. */ /* proc_t offset macro */#define PO(q) ((unsigned long)(&(((proc_t*)0)->q)))#include <ctype.h>#include <fcntl.h>#include <grp.h>#include <limits.h>#include <pwd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <sys/resource.h>#include <sys/types.h>#include <sys/mman.h>#include <time.h>#include <unistd.h>#include "../proc/readproc.h"#include "../proc/sysinfo.h"#include "../proc/status.h"#include "../proc/procps.h"#include "../proc/devname.h"#include "common.h"/* TODO: * Stop assuming system time is local time. */static char whitespace_and_outbuf[OUTBUF_SIZE + SPACE_AMOUNT + PAGE_SIZE*2];static char *outbuf = whitespace_and_outbuf+SPACE_AMOUNT;static char *whitespace = whitespace_and_outbuf;static unsigned max_rightward = 0x12345678; /* space for RIGHT stuff */static unsigned max_leftward = 0x12345678; /* space for LEFT stuff */static int wide_signals; /* true if we have room */static proc_t *pp; /* the process being printed */unsigned long seconds_since_boot;static unsigned long seconds_since_1970;static unsigned long time_of_boot;static unsigned long bytes_main_memory;static unsigned long page_shift;/*************************************************************************//************ Lots of sort functions, starting with the NOP **************/static int sr_nop(const proc_t* a, const proc_t* b){ (void)a;(void)b; /* shut up gcc */ return 0;}#define CMP_STR(NAME) \static int sr_ ## NAME(const proc_t* P, const proc_t* Q) { \ return strcmp(P-> ## NAME, Q-> ## NAME); \}#define CMP_INT(NAME) \static int sr_ ## NAME (const proc_t* P, const proc_t* Q) { \ if (P-> ## NAME < Q-> ## NAME) return -1; \ if (P-> ## NAME > Q-> ## NAME) return 1; \ return 0; \}CMP_INT(cutime)CMP_INT(cstime)CMP_INT(priority) /* nice */CMP_INT(timeout)CMP_INT(nice) /* priority */CMP_INT(rss) /* resident set size from stat file */ /* vm_rss, resident */CMP_INT(it_real_value)CMP_INT(size) /* total pages */ /* vm_size, vsize */CMP_INT(resident) /* resident pages */ /* vm_rss, rss */CMP_INT(share) /* shared pages */CMP_INT(trs) /* executable pages */CMP_INT(lrs) /* obsolete "library" pages above 0x60000000 */CMP_INT(drs) /* other pages (assumed data?) */CMP_INT(dt) /* dirty pages */CMP_INT(vm_size) /* kB VM */ /* size, vsize */CMP_INT(vm_lock) /* kB locked */CMP_INT(vm_rss) /* kB rss */ /* rss, resident */CMP_INT(vm_data) /* kB "data" == data-stack */CMP_INT(vm_stack) /* kB stack */CMP_INT(vm_exe) /* kB "exec" == exec-lib */CMP_INT(vm_lib) /* kB "libraries" */CMP_INT(vsize) /* pages VM */ /* size, vm_size */CMP_INT(rss_rlim)CMP_INT(flags)CMP_INT(min_flt)CMP_INT(maj_flt)CMP_INT(cmin_flt)CMP_INT(cmaj_flt)CMP_INT(nswap)CMP_INT(cnswap)CMP_INT(utime)CMP_INT(stime) /* Old: sort by systime. New: show start time. Uh oh. */CMP_INT(start_code)CMP_INT(end_code)CMP_INT(start_stack)CMP_INT(kstk_esp)CMP_INT(kstk_eip)CMP_INT(start_time)CMP_INT(wchan)/* CMP_STR(*environ) *//* CMP_STR(*cmdline) */CMP_STR(ruser)CMP_STR(euser)CMP_STR(suser)CMP_STR(fuser)CMP_STR(rgroup)CMP_STR(egroup)CMP_STR(sgroup)CMP_STR(fgroup)CMP_STR(cmd)/* CMP_STR(ttyc) */ /* FIXME -- use strncmp with 8 max */CMP_INT(ruid)CMP_INT(rgid)CMP_INT(euid)CMP_INT(egid)CMP_INT(suid)CMP_INT(sgid)CMP_INT(fuid)CMP_INT(fgid)CMP_INT(pid)CMP_INT(ppid)CMP_INT(pgrp)CMP_INT(session)CMP_INT(tty)CMP_INT(tpgid)CMP_INT(pcpu)CMP_INT(state)/***************************************************************************//************ Lots of format functions, starting with the NOP **************/static int pr_nop(void){ return sprintf(outbuf, "%c", '-');}/********* Unix 98 ************//***Only comm and args are allowed to contain blank characters; all others arenot. Any implementation-dependent variables will be specified in the systemdocumentation along with the default header and indicating if the fieldmay contain blank characters.Some headers do not have a standardized specifier!%CPU pcpu The % of cpu time used recently, with unspecified "recently".ADDR The address of the process.C Processor utilisation for scheduling.CMD The command name, or everything with -f.COMMAND args Command + args. May chop as desired. May use either version.COMMAND comm argv[0]ELAPSED etime Elapsed time since the process was started. [[dd-]hh:]mm:ssF Flags (octal and additive)GROUP group Effective group ID, prefer text over decimal.NI nice Decimal system scheduling priority, see nice(1).PGID pgid The decimal value of the process group ID.PID pid Decimal PID.PPID ppid Decimal PID.PRI Priority. Higher numbers mean lower priority.RGROUP rgroup Real group ID, prefer text over decimal.RUSER ruser Real user ID, prefer text over decimal.S The state of the process.STIME Starting time of the process.SZ The size in blocks of the core image of the process.TIME time Cumulative CPU time. [dd-]hh:mm:ssTT tty Name of tty in format used by who(1).TTY The controlling terminal for the process.UID UID, or name when -fUSER user Effective user ID, prefer text over decimal.VSZ vsz Virtual memory size in decimal kB.WCHAN Where waiting/sleeping or blank if running.The nice value is used to compute the priority.For some undefined ones, Digital does:F flag Process flags -- but in hex!PRI pri Process priorityS state Symbolic process statusTTY tt,tty,tname,longtname -- all do "ttyp1", "console", "??"UID uid Process user ID (effective UID)WCHAN wchan Address of event on which aFor some undefined ones, Sun does:ADDR addr memory address of the processC c Processor utilization for scheduling (obsolete).CMDF fS s state: OSRZTSTIME start time, printed w/o blanks. If 24h old, months & daysSZ size (in pages) of the swappable process's image in main memoryTTYUID uidWCHAN wchanFor some undefined ones, SCO does:ADDR addr Virtual address of the process' entry in the process table.SZ swappable size in kB of the virtual data and stackSTIME stime hms or md time format***//* Source & destination are known. Return bytes or screen characters? */static int forest_helper(void){ char *p = forest_prefix; char *q = outbuf; if(!*p) return 0; /* Arrrgh! somebody defined unix as 1 */ if(forest_type == 'u') goto unixy; p++; /* don't show everything as init's child */ while(*p){ switch(*p){ case ' ': strcpy(q, " "); break; case 'L': strcpy(q, " \\_ "); break; case '+': strcpy(q, " \\_ "); break; case '|': strcpy(q, " | "); break; case '\0': return q-outbuf; /* redundant & not used */ } q += 4; p++; } return q-outbuf; /* gcc likes this here */unixy: while(*p){ switch(*p){ case ' ': strcpy(q, " "); break; case 'L': strcpy(q, " "); break; case '+': strcpy(q, " "); break; case '|': strcpy(q, " "); break; case '\0': return q-outbuf; /* redundant & not used */ } q += 2; p++; } return q-outbuf; /* gcc likes this here */}/* XPG4-UNIX, according to Digital:The "args" and "command" specifiers show what was passed to the command.Modifications to the arguments are not shown.*//* * pp->cmd short accounting name (comm & ucomm) * pp->cmdline long name with args (args & command) * pp->environ environment *//* "command" is the same thing: long unless c */static int pr_args(void){ char *endp; endp = outbuf + forest_helper(); if(bsd_c_option){ endp += escape_str(endp, pp->cmd, PAGE_SIZE); /* short version */ }else{ const char **lc = (const char**)pp->cmdline; /* long version */ if(lc && *lc) { endp += escape_strlist(endp, lc, OUTBUF_SIZE); } else { char buf[ESC_STRETCH*PAGE_SIZE]; escape_str(buf, pp->cmd, ESC_STRETCH*PAGE_SIZE); endp += sprintf(endp, "[%s]", buf); } } if(bsd_e_option){ const char **env = (const char**)pp->environ; if(env && *env){ *endp++ = ' '; endp += escape_strlist(endp, env, OUTBUF_SIZE); } } return endp - outbuf;}/* "ucomm" is the same thing: short unless -f */static int pr_comm(void){ char *endp; endp = outbuf + forest_helper(); if(!unix_f_option){ /* does -f matter? */ endp += escape_str(endp, pp->cmd, PAGE_SIZE); /* short version */ }else{ const char **lc = (const char**)pp->cmdline; /* long version */ if(lc && *lc) { endp += escape_strlist(endp, lc, OUTBUF_SIZE); } else { char buf[ESC_STRETCH*PAGE_SIZE]; escape_str(buf, pp->cmd, ESC_STRETCH*PAGE_SIZE); endp += sprintf(endp, "[%s]", buf); } } if(bsd_e_option){ const char **env = (const char**)pp->environ; if(env && *env){ *endp++ = ' '; endp += escape_strlist(endp, env, OUTBUF_SIZE); } } return endp - outbuf;}/* Non-standard, from SunOS 5 */static int pr_fname(void){ char *endp; endp = outbuf + forest_helper(); endp += escape_str(endp, pp->cmd, 8); return endp - outbuf;}/* elapsed wall clock time, [[dd-]hh:]mm:ss format (not same as "time") */static int pr_etime(void){ unsigned t, dd,hh,mm,ss; int c = 0; t = ( ((unsigned long)seconds_since_boot) - ((unsigned long)pp->start_time) / Hertz );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -