• Home
  • Raw
  • Download

Lines Matching +full:qemu +full:- +full:user +full:- +full:static

1 /* ps.c - show process list
6 * And http://kernel.org/doc/Documentation/filesystems/proc.txt Table 1-4
9 * Deviations from posix: no -n because /proc/self/wchan exists; we use -n to
11 * Posix says default output should have field named "TTY" but if you "-o tty"
13 * Similarly -f outputs USER but calls it UID (we call it USER).
14 * It also says that -o "args" and "comm" should behave differently but use
16 * Select by session id is -s not -g. Posix doesn't say truncated fields
19 * Posix defines -o ADDR as "The address of the process" but the process
21 * field always prints "-" with an alignment of 1, which is why it has 11
22 * characters left for "cmd" in in 80 column "ps -l" mode. On x86-64 you
23 * need 12 chars, leaving nothing for cmd: I.E. posix 2008 ps -l mode can't
24 * be sanely implemented on 64 bit Linux systems. In procps there's ps -y
25 * which changes -l by removing the "F" column and swapping RSS for ADDR,
26 * leaving 9 chars for cmd, so we're using that as our -l output.
28 * Added a bunch of new -o fields posix doesn't mention, and we don't
29 * label "ps -o command,args,comm" as "COMMAND COMMAND COMMAND". We don't
30 * output argv[0] unmodified for -o comm or -o args (but procps violates
31 * posix for -o comm anyway, it's stat[2] not argv[0]).
36 * even though you can -o AIO there, to give sysadmins the option
39 * TODO: ps aux (att & bsd style "ps -ax" vs "ps ax" behavior difference)
40 * TODO: switch -fl to -y
41 * TODO: thread support /proc/$d/task/%d/stat (and -o stat has "l")
45 * TODO: pgrep -f only searches the amount of cmdline that fits in toybuf.
46 * TODO: pgrep qemu-system-i386 never matches because one char too long
54 USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
55 USE_PKILL(NEWTOY(pkill, "?Vu*U*t*s*P*g*G*fnovxl:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
61 usage: ps [-AadefLlnwZ] [-gG GROUP,] [-k FIELD,] [-o FIELD,] [-p PID,] [-t TTY,] [-uU USER,]
65 Which processes to show (-gGuUpPt selections may be comma separated lists):
67 -A All -a Has terminal not session leader
68 -d All but session leaders -e Synonym for -A
69 -g In GROUPs -G In real GROUPs (before sgid)
70 -p PIDs (--pid) -P Parent PIDs (--ppid)
71 -s In session IDs -t Attached to selected TTYs
72 -T Show threads also -u Owned by selected USERs
73 -U Real USERs (before suid)
77 -k Sort FIELDs (-FIELD to reverse) -M Measure/pad future field widths
78 -n Show numeric USER and GROUP -w Wide output (don't truncate fields)
80 Which FIELDs to show. (-o HELP for list, default = -o PID,TTY,TIME,CMD)
82 -f Full listing (-o USER:12=UID,PID,PPID,C,STIME,TTY,TIME,ARGS=CMD)
83 -l Long listing (-o F,S,UID,PID,PPID,C,PRI,NI,ADDR,SZ,WCHAN,TTY,TIME,CMD)
84 -o Output FIELDs instead of defaults, each with optional :size and =title
85 -O Add FIELDS to defaults
86 -Z Include LABEL
92 …usage: top [-Hhbq] [-k FIELD,] [-o FIELD,] [-s SORT] [-n NUMBER] [-m LINES] [-d SECONDS] [-p PID,]…
96 -H Show threads
97 -h Usage graphs instead of text
98 -k Fallback sort FIELDS (default -S,-%CPU,-ETIME,-PID)
99 -o Show FIELDS (def PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE)
100 -O Add FIELDS (replacing PR,NI,VIRT,RES,SHR,S from default)
101 -s Sort by field number (1-X, default 9)
102 -b Batch mode (no tty)
103 -d Delay SECONDS between each cycle (default 3)
104 -m Maximum number of tasks to show
105 -n Exit after NUMBER iterations
106 -p Show these PIDs
107 -u Show these USERs
108 -q Quiet (no header lines)
118 usage: iotop [-AaKObq] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]
122 -A All I/O, not just disk
123 -a Accumulated I/O (not percentage)
124 -H Show threads
125 -K Kilobytes
126 -k Fallback sort FIELDS (default -[D]IO,-ETIME,-PID)
127 -m Maximum number of tasks to show
128 -O Only show processes doing I/O
129 -o Show FIELDS (default PID,PR,USER,[D]READ,[D]WRITE,SWAP,[D]IO,COMM)
130 -s Sort by field number (0-X, default 6)
131 -b Batch mode (no tty)
132 -d Delay SECONDS between each cycle (default 3)
133 -n Exit after NUMBER iterations
134 -p Show these PIDs
135 -u Show these USERs
136 -q Quiet (no header lines)
145 …usage: pgrep [-clfnovx] [-d DELIM] [-L SIGNAL] [PATTERN] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,]…
150 -c Show only count of matches
151 -d Use DELIM instead of newline
152 -L Send SIGNAL instead of printing name
153 -l Show command name
154 -f Check full command line for PATTERN
155 -G Match real Group ID(s)
156 -g Match Process Group(s) (0 is current user)
157 -n Newest match only
158 -o Oldest match only
159 -P Match Parent Process ID(s)
160 -s Match Session ID(s) (0 for current)
161 -t Match Terminal(s)
162 -U Match real User ID(s)
163 -u Match effective User ID(s)
164 -v Negate the match
165 -x Match whole command (not substring)
171 …usage: pkill [-fnovx] [-SIGNAL|-l SIGNAL] [PATTERN] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t …
173 -l Send SIGNAL (default SIGTERM)
174 -V Verbose
175 -f Check full command line for PATTERN
176 -G Match real Group ID(s)
177 -g Match Process Group(s) (0 is current user)
178 -n Newest match only
179 -o Oldest match only
180 -P Match Parent Process ID(s)
181 -s Match Session ID(s) (0 for current)
182 -t Match Terminal(s)
183 -U Match real User ID(s)
184 -u Match effective User ID(s)
185 -v Negate the match
186 -x Match whole command (not substring)
226 // Linked list of -o fields selected for display, in order, with :len and =title
241 * https://kernel.org/doc/Documentation/filesystems/proc.txt table 1-4) but
250 SLOT_cmajflt, /*major faults+child*/ SLOT_utime, // user+kernel jiffies
260 SLOT_utime2, /*relative utime (top)*/ SLOT_uid, // user id
261 SLOT_ruid, /*real user id*/ SLOT_gid, // group id
268 SLOT_upticks, /*uptime-starttime*/ SLOT_argv0len, // argv[0] length
293 /* The typos[] array lists all the types understood by "ps -o", I.E all the
296 * name: the column name, displayed at top and used to select column with -o
313 * if (TT.bits & _PS_NAME) printf("-o included PS_NAME");
318 // TODO: Android uses -30 for LABEL, but ideally it would auto-size.
322 } static const typos[] = TAGGED_ARRAY(PS,
327 {"NI", "Niceness (static 19 to -20)", 3, SLOT_nice},
335 {"PR", "Prio Reversed (dyn 39-0, RT)", 2, SLOT_priority},
345 // String fields (-1 is procpid->str, rest are str+offset[1-slot])
346 {"TTY", "Controlling terminal", -8, -2},
347 {"WCHAN", "Wait location in kernel", -6, -3},
348 {"LABEL", "Security label", -30, -4},
349 {"COMM", "EXE filename (/proc/PID/exe)", -27, -5},
350 {"NAME", "Process name (PID's argv[0])", -27, -7},
351 {"COMMAND", "EXE path (/proc/PID/exe)", -27, -5},
352 {"CMDLINE", "Command line (argv[])", -27, -6},
353 {"ARGS", "CMDLINE minus initial path", -27, -6},
354 {"CMD", "Thread name (/proc/TID/stat:2)", -15, -1},
356 // user/group (may call getpwuid() or similar)
357 {"UID", "User id", 5, SLOT_uid},
358 {"USER", "User name", -12, XX|SLOT_uid},
359 {"RUID", "Real (before suid) user ID", 4, SLOT_ruid},
360 {"RUSER", "Real (before suid) user name", -8, XX|SLOT_ruid},
362 {"GROUP", "Group name", -8, XX|SLOT_gid},
364 {"RGROUP", "Real (before sgid) group name", -8, XX|SLOT_rgid},
371 // Percentage displays (fixed point, one decimal digit. 123 -> 12.3)
397 -1, XX},
401 -5, XX},
405 // Show sorted "-o help" text for fields listed in toybuf[len]
406 static void help_fields(int len, int multi) in help_fields()
412 for (j = len; j--; ) { in help_fields()
413 k = -1; in help_fields()
422 if (k == -1) break; in help_fields()
428 if (strlen(t->help)>30) { in help_fields()
429 if (multi) printf(" %-8s%s\n", t->name, t->help); in help_fields()
430 else j--; in help_fields()
433 printf(" %-8s%*s%c"+2*!left, t->name, -30*left, t->help, 10+22*left); in help_fields()
439 // Print help text for each -o field, with categories.
440 static void help_help(void) in help_help()
442 int i, jump = PS_CMD+1-PS_COMM; in help_help()
444 // TODO: sort the array of -o types so they're already alphabetical and in help_help()
448 // First show the half-dozen variants of command line display. in help_help()
454 // Show the rest of the -o types, starting with the ones that don't columnize in help_help()
457 for (i = 0; i<ARRAY_LEN(typos)-jump; i++) toybuf[i] = i+(i>=PS_COMM)*jump; in help_help()
458 help_fields(ARRAY_LEN(typos)-jump, 1); in help_help()
459 help_fields(ARRAY_LEN(typos)-jump, 0); in help_help()
465 static int shared_match_process(long long *slot) in shared_match_process()
475 // Do we have -g -G -p -P -s -t -u -U options selecting processes? in shared_match_process()
479 if (mm->len) { in shared_match_process()
480 ll = mm->ptr; in shared_match_process()
481 for (j = 0; j<mm->len; j++) if (ll[j] == slot[match[i].len]) return 1; in shared_match_process()
485 return ll ? 0 : -1; in shared_match_process()
489 static int ps_match_process(long long *slot) in ps_match_process()
507 static char *string_field(struct procpid *tb, struct ofields *field) in string_field()
509 char *buf = toybuf+sizeof(toybuf)-260, *out = buf, *s; in string_field()
510 int which = field->which, sl = typos[which].slot; in string_field()
511 long long *slot = tb->slot, ll = (sl >= 0) ? slot[sl&(XX-1)] : 0; in string_field()
517 if (which==PS_PRI) ll = 39-ll; in string_field()
522 else if (which==PS_PR && ll<-9) fmt="RT"; in string_field()
523 else if ((which==PS_RTPRIO || which==PS_BIT) && ll == 0) fmt="-"; in string_field()
528 out = tb->str; in string_field()
529 sl *= -1; in string_field()
530 // First string slot has offset 0, others are offset[-slot-2] in string_field()
531 if (--sl) out += tb->offset[--sl]; in string_field()
540 if (which>=PS_COMM && !*out) sprintf(out = buf, "[%s]", tb->str); in string_field()
542 // user/group in string_field()
549 if (gr) out = gr->gr_name; in string_field()
553 if (pw) out = pw->pw_name; in string_field()
565 if (which==PS_ELAPSED) ll = (slot[SLOT_uptime]*j)-slot[SLOT_starttime]; in string_field()
568 // Output days-hours:mins:secs, skipping non-required fields with zero in string_field()
575 if ((*s = "-::"[j])) s++; in string_field()
580 if (which==PS_TIME_ && s-out<8) in string_field()
585 ll = slot[sl&(XX-1)]*1000; in string_field()
596 int i = abs(field->len); in string_field()
601 ll = -ll; in string_field()
602 *s++ = '-'; in string_field()
603 if (i>4) i--; in string_field()
607 else human_readable_long(s, ll, i-1, 0, 0); in string_field()
614 *s++ = tb->state; in string_field()
625 time_t t = time(0)-slot[SLOT_uptime]+slot[SLOT_starttime]/TT.ticks; in string_field()
629 // so move start address so yyyy-mm-dd hh:mm revealed on left at :16, in string_field()
632 out = out+strlen(out)-3-abs(field->len); in string_field()
642 static void show_ps(void *p) in show_ps()
649 for (scroll = TT.scroll; scroll && field->next; scroll--) field = field->next; in show_ps()
652 for (; field; field = field->next) { in show_ps()
661 width--; in show_ps()
666 abslen = abs(field->len); in show_ps()
667 sign = field->len<0 ? -1 : 1; in show_ps()
669 if ((field->which<=PS_BIT || FLAG(w)) && olen>abslen) { in show_ps()
671 extra += olen-abslen; in show_ps()
674 int unused = abslen-olen; in show_ps()
678 abslen -= unused; in show_ps()
679 extra -= unused; in show_ps()
686 if (!field->next && sign<0) { in show_ps()
687 pad = -1; in show_ps()
691 // If we truncated a left-justified field, show + instead of last char in show_ps()
693 width--; in show_ps()
694 len--; in show_ps()
695 if (field->next) pad++; in show_ps()
699 if (TT.tty) width -= draw_trim(out, pad, len); in show_ps()
700 else width -= printf("%*.*s", pad, len, out); in show_ps()
708 // Fills toybuf with struct procpid and either DIRTREE_SAVEs a copy to ->extra
709 // (in -k mode) or calls show_ps directly on toybuf (for low memory systems).
710 static int get_ps(struct dirtree *new) in get_ps()
714 long long bits; // Only fetch extra data if an -o field is displaying it in get_ps()
716 // sources for procpid->offset[] data in get_ps()
722 long long *slot = tb->slot; in get_ps()
723 char *name, *s, *buf = tb->str, *end = 0; in get_ps()
728 // Recurse one level into /proc children, skip non-numeric entries in get_ps()
729 if (!new->parent) in get_ps()
734 memset(slot, 0, sizeof(tb->slot)); in get_ps()
735 slot[SLOT_tid] = *slot = atol(new->name); in get_ps()
736 if (TT.threadparent && TT.threadparent->extra) { in get_ps()
737 struct procpid *tb2 = (struct procpid *)TT.threadparent->extra; in get_ps()
739 *slot = *tb2->slot; in get_ps()
741 // to get non-collated info for just parent thread (vs whole process). in get_ps()
742 if (*slot == slot[SLOT_tid]) slot = tb2->slot; in get_ps()
751 // parse oddball fields: the first field is same as new->name (skip it) in get_ps()
752 // and the second and third (name and state) are the only non-numeric fields. in get_ps()
758 if (!end || end-name>255) return 0; in get_ps()
759 if (1>sscanf(s = end, ") %c%n", &tb->state, &i)) return 0; in get_ps()
768 // and convert low chars to ? for non-tty display while we're at it. in get_ps()
769 for (i = 0; i<end-name; i++) in get_ps()
770 if ((tb->str[i] = name[i]) < ' ') in get_ps()
771 if (!TT.tty) tb->str[i] = '?'; in get_ps()
772 buf = tb->str+i; in get_ps()
774 len = sizeof(toybuf)-(buf-toybuf); in get_ps()
778 // save uid, ruid, gid, gid, and rgid int slots 31-34 (we don't use sigcatch in get_ps()
781 slot[SLOT_uid] = new->st.st_uid; in get_ps()
782 slot[SLOT_gid] = new->st.st_gid; in get_ps()
797 slot[SLOT_ruid] = s ? atol(s) : new->st.st_uid; in get_ps()
799 slot[SLOT_rgid] = s ? atol(s) : new->st.st_gid; in get_ps()
819 if (slot != tb->slot) return 0; in get_ps()
825 // systems (or ps | more) we re-fetch uptime as we fetch each /proc line. in get_ps()
829 slot[SLOT_upticks] = slot[SLOT_uptime]*TT.ticks - slot[SLOT_starttime]; in get_ps()
858 // Done using buf[] (tb->str) as scratch space, now read string data, in get_ps()
860 // str->offset to avoid strlen() loop to find relevant string.) in get_ps()
868 // and what -o display field outputs it (to skip the ones we don't need). in get_ps()
872 tb->offset[j] = buf-(tb->str); in get_ps()
879 // each string we haven't checked yet, tb->str starts after the numeric in get_ps()
884 len = sizeof(toybuf)-256*(ARRAY_LEN(fetch)-j)-(buf-toybuf)-260; in get_ps()
888 // for -o NAME (j==5) copy data from threadparent (PID) into thread (TID). in get_ps()
894 if (TT.threadparent && TT.threadparent->extra) in get_ps()
895 ptb = (void *)TT.threadparent->extra; in get_ps()
899 if (j==3) i = strlen(s = ptb->str+ptb->offset[3]); in get_ps()
902 i = ptb->slot[SLOT_argv0len]; in get_ps()
903 s = ptb->str+ptb->offset[4]; in get_ps()
904 while (-1!=(k = stridx(s, '/')) && k<i) { in get_ps()
906 i -= k+1; in get_ps()
954 if (strstart(&s, "/dev/")) memmove(buf, s, len -= 4); in get_ps()
966 if (!buf[len-1] || isspace(buf[len-1])) buf[--len] = 0; in get_ps()
969 // Turn NUL to space, other low ascii to ? (in non-tty mode), except in get_ps()
971 for (i=0; i<len-1; i++) { in get_ps()
987 // Each case above calculated/retained len, so we don't need to re-strlen. in get_ps()
1000 s = xmalloc(buf-toybuf); in get_ps()
1001 new->extra = (long)s; in get_ps()
1002 memcpy(s, toybuf, buf-toybuf); in get_ps()
1008 static int get_threads(struct dirtree *new) in get_threads()
1014 if (!new->parent) return get_ps(new); in get_threads()
1015 pid = atol(new->name); in get_threads()
1029 new->child = dirtree_flagread(toybuf, DIRTREE_SHUTUP|DIRTREE_PROC, get_ps); in get_threads()
1030 if (new->child == DIRTREE_ABORTVAL) new->child = 0; in get_threads()
1032 kcount = TT.kcount-kcount+1; in get_threads()
1033 tb = (void *)new->extra; in get_threads()
1034 tb->slot[SLOT_tcount] = kcount; in get_threads()
1038 if (new->child) for (dt = new->child->child; dt; dt = dt->next) { in get_threads()
1039 tb = (void *)dt->extra; in get_threads()
1040 tb->slot[SLOT_pid] = pid; in get_threads()
1041 tb->slot[SLOT_tcount] = kcount; in get_threads()
1046 TT.show_process((void *)new->extra); in get_threads()
1047 if ((dt = new->child)) { in get_threads()
1048 new->child = 0; in get_threads()
1049 while (dt->child) { in get_threads()
1050 new = dt->child->next; in get_threads()
1051 TT.show_process((void *)dt->child->extra); in get_threads()
1052 free(dt->child); in get_threads()
1053 dt->child = new; in get_threads()
1062 static char *parse_ko(void *data, char *type, int length) in parse_ko()
1068 // Caller's WOULD_EXIT catches -o help and prints help in parse_ko()
1074 if ((end = strchr(type, '=')) && length>(end-type)) { in parse_ko()
1076 length -= (end-type)+1; in parse_ko()
1084 if (!title) length = width-type; in parse_ko()
1091 memcpy(field->title = (char *)(field+1), title, length); in parse_ko()
1092 field->title[field->len = length] = 0; in parse_ko()
1096 field->len = strtol(++width, &title, 10); in parse_ko()
1098 end = --width; in parse_ko()
1102 field->reverse = 1; in parse_ko()
1103 if (*type == '-') field->reverse = -1; in parse_ko()
1104 else if (*type != '+') type--; in parse_ko()
1107 field->which = i; in parse_ko()
1111 else if (-1==(k = stridx((char []){PS_NI, PS_SCH, PS_ELAPSED, PS__CPU, in parse_ko()
1116 if (!strncasecmp(type, s, end-type) && strlen(s)==end-type) break; in parse_ko()
1121 if (!field->title) field->title = typos[field->which].name; in parse_ko()
1122 k = i<2 ? TT.pidlen : typos[field->which].width; in parse_ko()
1123 if (!field->len) field->len = k; in parse_ko()
1124 else if (k<0) field->len *= -1; in parse_ko()
1132 static long long get_headers(struct ofields *field, char *buf, int blen) in get_headers()
1138 for (scroll = TT.scroll; scroll && field->next; scroll--) field = field->next; in get_headers()
1140 for (; field; field = field->next) { in get_headers()
1141 len += snprintf(buf+len, blen-len, " %*s"+!bits, field->len, in get_headers()
1142 field->title); in get_headers()
1143 bits |= 1LL<<field->which; in get_headers()
1149 // Parse command line options -p -s -t -u -U -g -G
1150 static char *parse_rest(void *data, char *str, int len) in parse_rest()
1153 long *ll = pl->ptr; in parse_rest()
1158 if (!(15&pl->len)) in parse_rest()
1159 ll = pl->ptr = xrealloc(pl->ptr, sizeof(long)*(pl->len+16)); in parse_rest()
1163 ll[pl->len] = xstrtol(str, &end, 10); in parse_rest()
1165 // For pkill, -s 0 represents pkill's session id. in parse_rest()
1166 if (pl==&TT.ss && ll[pl->len]==0) ll[pl->len] = getsid(0); in parse_rest()
1170 if (num && ll[pl->len]>0) { in parse_rest()
1171 pl->len++; in parse_rest()
1176 // -t pts = 12,pts/12 tty = /dev/tty2,tty2,S0 in parse_rest()
1178 if (strstart(&str, strcpy(toybuf, "/dev/"))) len -= 5; in parse_rest()
1180 len -= 4; in parse_rest()
1182 } else if (strstart(&str, "tty")) len -= 3; in parse_rest()
1184 if (len<256 && (!(end = strchr(str, '/')) || end-str>len)) { in parse_rest()
1191 ll[pl->len++] = st.st_rdev; in parse_rest()
1199 pl->len++; in parse_rest()
1209 ll[pl->len++] = gr->gr_gid; in parse_rest()
1216 ll[pl->len++] = pw->pw_uid; in parse_rest()
1227 // sort processes by FIELD(s) listed in option -k
1228 static int ksort(void *aa, void *bb) in ksort()
1234 for (field = TT.kfields; field && !ret; field = field->next) { in ksort()
1235 slot = typos[field->which].slot; in ksort()
1238 /* fix "ps -eo pid,cmd,%cpu --sort=-%CPU"sort not correct problem */ in ksort()
1240 if (field->which == PS__CPU) { in ksort()
1241 double delta = atof(string_field(ta, field)) - atof(string_field(tb, field)); in ksort()
1242 ret = (delta > -EXP) - (delta < EXP); in ksort()
1243 ret *= field->reverse; in ksort()
1250 if (ta->slot[slot]<tb->slot[slot]) ret = -1; in ksort()
1251 if (ta->slot[slot]>tb->slot[slot]) ret = 1; in ksort()
1260 ret *= field->reverse; in ksort()
1266 // Collect ->extra field from leaf nodes DIRTREE_SAVEd by get_ps() into array
1268 static struct procpid **collate_leaves(struct procpid **tb, struct dirtree *dt) in collate_leaves()
1271 struct dirtree *next = dt->next; in collate_leaves()
1273 if (dt->extra) *(tb++) = (void *)dt->extra; in collate_leaves()
1274 if (dt->child) tb = collate_leaves(tb, dt->child); in collate_leaves()
1282 // Allocate struct procpid array of length count and populate it with ->extra
1284 static struct procpid **collate(int count, struct dirtree *dt) in collate()
1293 // parse command line arguments (ala -k -o) with a comma separated FIELD list
1294 static void default_ko(char *s, void *fields, char *err, struct arg_list *arg) in default_ko()
1305 static void common_setup(void) in common_setup()
1312 if (-1 != (i = tty_fd())) { in common_setup()
1332 // If we can't query terminal size pad to 80 but do -w in ps_main()
1337 // parse command line options other than -o in ps_main()
1338 comma_args(TT.ps.P, &TT.PP, "bad -P", parse_rest); in ps_main()
1339 comma_args(TT.ps.p, &TT.pp, "bad -p", parse_rest); in ps_main()
1340 comma_args(TT.ps.t, &TT.tt, "bad -t", parse_rest); in ps_main()
1341 comma_args(TT.ps.s, &TT.ss, "bad -s", parse_rest); in ps_main()
1342 comma_args(TT.ps.u, &TT.uu, "bad -u", parse_rest); in ps_main()
1343 comma_args(TT.ps.U, &TT.UU, "bad -U", parse_rest); in ps_main()
1344 comma_args(TT.ps.g, &TT.gg, "bad -g", parse_rest); in ps_main()
1345 comma_args(TT.ps.G, &TT.GG, "bad -G", parse_rest); in ps_main()
1346 comma_args(TT.ps.k, &TT.kfields, "bad -k", parse_ko); in ps_main()
1349 // It's undocumented, but traditionally extra arguments are extra -p args in ps_main()
1357 "USER:12=UID,%%sPPID,%s,STIME,TTY,TIME,ARGS=CMD", FLAG(T) ? "TCNT" :"C"); in ps_main()
1362 "USER,%%sPPID,VSIZE:10,RSS,WCHAN:10,ADDR:10,S,%s", in ps_main()
1368 default_ko(toybuf, &TT.fields, "bad -o", TT.ps.o); in ps_main()
1371 if (TT.fields) TT.fields = ((struct ofields *)TT.fields)->prev; in ps_main()
1372 comma_args(TT.ps.O, &TT.fields, "bad -O", parse_ko); in ps_main()
1373 if (TT.fields) TT.fields = ((struct ofields *)TT.fields)->next; in ps_main()
1377 // -f and -n change the meaning of some fields in ps_main()
1381 for (field = TT.fields; field; field = field->next) { in ps_main()
1382 if (FLAG(n) && field->which>=PS_UID in ps_main()
1383 && field->which<=PS_RGROUP && (typos[field->which].slot&XX)) in ps_main()
1384 field->which--; in ps_main()
1405 for (field = TT.fields; field; field = field->next) { in ps_main()
1408 if (abs(field->len)<len) field->len = (field->len<0) ? -len : len; in ps_main()
1412 // Now that we've recalculated field widths, re-pad headers again in ps_main()
1442 // select which of the -o fields to sort by
1443 static void setsort(int pos) in setsort()
1450 for (field = TT.fields; field; field = field->next) { in setsort()
1451 if ((TT.sortpos = i++)<pos && field->next) continue; in setsort()
1453 field2->which = field->which; in setsort()
1454 field2->len = field->len; in setsort()
1462 static int merge_deltas(long long *oslot, long long *nslot, int milis) in merge_deltas()
1469 oslot[deltas[i]] = nslot[deltas[i]] - oslot[deltas[i]]; in merge_deltas()
1475 static int header_line(int line, int rev) in header_line()
1481 printf("%s%-*.*s%s\r\n", rev?"\e[7m":"", rev?TT.width:0, TT.width, toybuf, in header_line()
1485 return line-1; in header_line()
1488 static void top_cursor_cleanup(void) in top_cursor_cleanup()
1494 static void bargraph(char *label, unsigned width, unsigned long span[4]) in bargraph()
1513 else printf("\e[%um", (char[]){32,34,31}[color-1]); in bargraph()
1516 if (color<4) ll -= *span; in bargraph()
1517 printf("%c", width-i>len ? (color==4 ? ' ' : '|') : percent[len-(width-i)]); in bargraph()
1523 static int cmp_lt(struct procpid *x, struct procpid *y) in cmp_lt()
1526 return (x->slot[SLOT_pid] < y->slot[SLOT_pid]) || in cmp_lt()
1527 (x->slot[SLOT_pid] == y->slot[SLOT_pid] && x->slot[SLOT_tid] < y->slot[SLOT_tid]); in cmp_lt()
1530 static void top_common( in top_common()
1539 char scratch[16], *pos, *cpufields[] = {"user", "nice", "sys", "idle", in top_common()
1545 if (!TT.fields) perror_exit("no -o"); in top_common()
1565 plnew->whence = millitime(); in top_common()
1569 plnew->tb = collate(plnew->count = TT.kcount, dt); in top_common()
1575 // user nice system idle iowait irq softirq host in top_common()
1581 if (!plold->tb) { in top_common()
1599 old.count--; in top_common()
1608 if (filter(otb->slot, ntb->slot, new.whence-old.whence)) { in top_common()
1613 old.count--; in top_common()
1616 new.count--; in top_common()
1619 // Don't re-fetch data if it's not time yet, just re-display existing data. in top_common()
1633 /* fix "iotop -m 10" show 13 lines problem*/ in top_common()
1635 if (toys.which->name[0] == 'i') { in top_common()
1650 if (*toys.which->name == 't') { in top_common()
1673 if (readfile("/proc/meminfo", toybuf+256, sizeof(toybuf)-256)) { in top_common()
1682 if (j==1) human_readable_long(hr[1], (run[i-1]-run[i])>>(10*k), in top_common()
1692 unsigned long swp[] = {run[3], 0, 0, run[3]-run[4]}, in top_common()
1693 mem[] = {run[0], run[0]-run[1]-run[2]-run[5], run[2], run[5]}; in top_common()
1705 // advance, so calculate idle time as potential time - used. in top_common()
1706 if (mix.count) up = mix.tb[0]->slot[SLOT_upticks]; in top_common()
1710 for (i = 0; i<8; i++) ll += stats[i]-stats[i+8]; in top_common()
1711 stats[3] = now - llabs(ll); in top_common()
1714 ll = (llabs(stats[i]-stats[i+8])*1000)/up; in top_common()
1724 for (field = TT.fields; field; field = field->next) { in top_common()
1726 int slot = typos[field->which].slot&(XX-1); in top_common()
1728 if (field->which<PS_C || field->which>PS_DIO) continue; in top_common()
1729 ll = 1LL<<field->which; in top_common()
1733 tb.slot[slot] += mix.tb[i]->slot[slot]; in top_common()
1734 pos += snprintf(pos, sizeof(toybuf)/2-(pos-toybuf), in top_common()
1735 " %s: %*s,", typos[field->which].name, in top_common()
1736 field->len, string_field(&tb, field)); in top_common()
1738 *--pos = 0; in top_common()
1748 pos[-1] = '['; in top_common()
1751 if (FLAG(b)) while (isspace(*(pos-1))) --pos; in top_common()
1755 if (!recalc && !FLAG(b)) printf("\e[%dH\e[J", 1+TT.height-lines); in top_common()
1759 int bold = !FLAG(b) && mix.tb[i+topoff]->state == 'R'; in top_common()
1767 if (TT.top.n && !--TT.top.n) { in top_common()
1778 msleep(timeout-now); in top_common()
1785 i = scan_key_getsize(scratch, timeout-now, &TT.width, &TT.height); in top_common()
1786 if (i==-1 || i==3 || toupper(i)=='Q') { in top_common()
1790 if (i==-2) break; in top_common()
1792 /* fix "top -n 5" show 3 times problem*/ in top_common()
1793 if (i==-3) { in top_common()
1798 if (i==-3) continue; in top_common()
1806 ((struct ofields *)TT.kfields)->reverse *= -1; in top_common()
1808 i -= 256; in top_common()
1809 if (i == (KEY_SHIFT|KEY_LEFT)) setsort(TT.sortpos-1); in top_common()
1812 else if (i == KEY_LEFT && TT.scroll) TT.scroll--; in top_common()
1813 else if (recalc-- && i == KEY_UP) topoff--; in top_common()
1816 else if (i == KEY_PGUP) topoff -= lines; in top_common()
1824 for (i=0; i<plold->count; i++) free(plold->tb[i]); in top_common()
1825 free(plold->tb); in top_common()
1831 static void top_setup(char *defo, char *defk) in top_setup()
1844 comma_args(TT.top.u, &TT.uu, "bad -u", parse_rest); in top_setup()
1845 comma_args(TT.top.p, &TT.pp, "bad -p", parse_rest); in top_setup()
1848 default_ko(defo, &TT.fields, "bad -o", TT.top.o); in top_setup()
1852 default_ko("-S", &TT.kfields, 0, 0); in top_setup()
1853 default_ko(defk, &TT.kfields, "bad -k", TT.top.k); in top_setup()
1855 setsort(TT.top.s-1); in top_setup()
1860 sprintf(toybuf, "%cID,USER,%s%%CPU,%%MEM,TIME+,%s", FLAG(H) ? 'T' : 'P', in top_main()
1864 top_setup(toybuf, "-%CPU,-ETIME,-PID"); in top_main()
1868 field = field->next->next; in top_main()
1869 comma_args(TT.top.O, &field, "bad -O", parse_ko); in top_main()
1879 static int iotop_filter(long long *oslot, long long *nslot, int milis) in iotop_filter()
1883 else oslot[SLOT_upticks] = ((millitime()-TT.time)*TT.ticks)/1000; in iotop_filter()
1894 top_setup(s1 = xmprintf("PID,PR,USER,%sREAD,%sWRITE,SWAP,%sIO,COMM",d,d,d), in iotop_main()
1895 s2 = xmprintf("-%sIO,-ETIME,-PID",d)); in iotop_main()
1913 static void do_pgk(struct procpid *tb) in do_pgk()
1916 if (kill(*tb->slot, TT.pgrep.signal)) { in do_pgk()
1920 perror_msg("%s->%lld", s, *tb->slot); in do_pgk()
1924 printf("%lld", *tb->slot); in do_pgk()
1925 if (FLAG(l)) printf(" %s", tb->str+tb->offset[4]*FLAG(f)); in do_pgk()
1930 static void match_pgrep(void *p) in match_pgrep()
1935 char *name = tb->str+tb->offset[4]*FLAG(f); in match_pgrep()
1938 if (TT.pgrep.self == *tb->slot) return; in match_pgrep()
1941 for (reg = TT.pgrep.regexes; reg; reg = reg->next) { in match_pgrep()
1942 if (regexec(&reg->reg, name, 1, &match, 0)) continue; in match_pgrep()
1953 // Repurpose a field for -c count. in match_pgrep()
1956 long long ll = tb->slot[SLOT_starttime]; in match_pgrep()
1958 if (FLAG(o)) ll *= -1; in match_pgrep()
1962 TT.pgrep.snapshot = xmemdup(toybuf, (name+strlen(name)+1)-toybuf); in match_pgrep()
1966 static int pgrep_match_process(long long *slot) in pgrep_match_process()
1969 /* fix "pgrep -v sh" no show info problem*/ in pgrep_match_process()
1986 error_exit("bad -L '%s'", TT.pgrep.L); in pgrep_main()
1988 comma_args(TT.pgrep.G, &TT.GG, "bad -G", parse_rest); in pgrep_main()
1989 comma_args(TT.pgrep.g, &TT.gg, "bad -g", parse_rest); in pgrep_main()
1990 comma_args(TT.pgrep.P, &TT.PP, "bad -P", parse_rest); in pgrep_main()
1991 comma_args(TT.pgrep.s, &TT.ss, "bad -s", parse_rest); in pgrep_main()
1992 comma_args(TT.pgrep.t, &TT.tt, "bad -t", parse_rest); in pgrep_main()
1993 comma_args(TT.pgrep.U, &TT.UU, "bad -U", parse_rest); in pgrep_main()
1994 comma_args(TT.pgrep.u, &TT.uu, "bad -u", parse_rest); in pgrep_main()
2003 xregcomp(&reg->reg, *arg, REG_EXTENDED); in pgrep_main()
2004 reg->next = TT.pgrep.regexes; in pgrep_main()
2029 if (!FLAG(l) && *args && **args=='-') TT.pgrep.L = *(args++)+1; in pkill_main()