Merge branch 'master', remote-tracking branch 'sami/ng'

This commit is contained in:
Craig Small 2011-10-20 22:15:27 +11:00
commit e383fe2622
19 changed files with 569 additions and 131 deletions

99
FAQ Normal file
View File

@ -0,0 +1,99 @@
Why does "ps -aux" complain about a bogus '-'?
According to the POSIX and UNIX standards, the above command asks to display
all processes with a TTY (generally the commands users are running) plus all
processes owned by a user named "x". If that user doesn't exist, then ps will
assume you really meant "ps aux". The warning is given to gently break you of a
habit that will cause you trouble if a user named "x" were created.
Why don't I see SMP (per-CPU) stats in top?
You didn't enable it. Press '?' for built-in help or read the man page. Per-CPU
stats are disabled by default because they take up too much space. Some Linux
systems have hundreds of CPUs.
Why do long usernames get printed as numbers?
The UNIX and POSIX standards require that user names and group names be printed
as decimal integers when there is not enough room in the column. Truncating the
names, besides being a violation of the standard, would lead to confusion
between names like MichelleRichards and MichelleRichardson. The UNIX and POSIX
way to change column width is to rename the column:
ps -o pid,user=CumbersomeUserNames -o comm
The easy way is to directly specify the desired width:
ps -o pid,user:19,comm
Why is %CPU underreported for multi-threaded (Java, etc.) apps?
You need to upgrade to the 2.6.10 kernel at least. Older kernels do not provide
a reasonable way to get this information.
Why do ps and top show threads individually?
The 2.4.xx kernel does not provide proper support for grouping threads by
process. Hacks exist to group them anyway, but such hacks will falsely group
similar tasks and will fail to group tasks due to race conditions. The hacks
are also slow. As none of this is acceptable in a critical system tool, task
grouping is not currently available for the 2.4.xx kernel. The 2.6.xx kernel
allows for proper thread grouping and reporting. To take advantage of this,
your programs must use a threading library that features the CLONE_THREAD flag.
The NPTL pthreads provided by recent glibc releases use CLONE_THREAD.
What systems are supported?
Linux 2.4.xx and 2.6.xx are commonly tested and expected to work well. SMP is
well supported. Multi-node cluster views require a multi-node /proc filesystem;
without that you will see a single-node view.
Where to I send bug reports?
You may use the Debian bug tracking system or send your report to
procps@freelists.org (no subscription required) instead.
Why are there so many procps projects?
The original maintainer seems to have had little time for procps. Whatever his
reasons, the project didn't get maintained. Starting in 1997, Albert Cahalan
wrote a new ps program for the package. For the next few years, Albert quietly
helped the Debian package maintainer fix bugs. In 2001, Rik van Riel decided to
do something about what appeared to be the lack of a maintainer. He picked up
the buggy old code in Red Hat's CVS and started adding patches. Meanwhile,
other people have patched procps in a great many ways.
In 2002, Albert moved procps to http://procps.sourceforge.net. This was done to
ensure that years of testing and bug fixes would not be lost. The major version
number was changed to 3, partly to avoid confusing users and partly because the
top program had been redone.
After development essentially stopped on sourceforge.net, in 2011 the project
found a new home at http://gitorious.org/procps. This represents the Debian,
Fedora and openSUSE fork of procps. To avoid confusion and potential name
clashes the package is now known as procps-ng (next generation), the version
number was raised to 3.3.0 and the library soname changed to libproc-ng-3.3.0.
What is being done to procps-ng at its new home?
All programs are in the process of being modernized, both in terms of coding
style and supporting documentation. Autotools have been integrated and the
library API has been expanded with many new fields supported such as control
groups, supplementary groups, etc. The top program has been rewritten offering
many new capabilities while providing performance improvements up to 300%.
Why does ps get signal 17?
No ps release has ever had this problem. Most likely your system has been
broken into. You might want to install a more recent version of the OS. If
you'd rather take your chances, simply upgrade procps.

View File

@ -9,9 +9,6 @@ AM_LDFLAGS = ./proc/libproc-ng.la
sbin_PROGRAMS = \
sysctl
bin_PROGRAMS = \
kill
usrbin_exec_PROGRAMS = \
free \
pgrep \
@ -27,7 +24,6 @@ usrbin_exec_PROGRAMS = \
dist_man_MANS = \
free.1 \
kill.1 \
pgrep.1 \
pkill.1 \
pmap.1 \
@ -41,6 +37,11 @@ dist_man_MANS = \
vmstat.8 \
w.1
if BUILD_KILL
bin_PROGRAMS = kill
dist_man_MANS += kill.1
endif
if HAVE_NCURSES
usrbin_exec_PROGRAMS += \
slabtop \
@ -64,12 +65,13 @@ sysconf_DATA = sysctl.conf
EXTRA_DIST = \
autogen.sh \
BUGS \
CodingStyle \
contrib/dummy.c \
contrib/minimal.c \
contrib/tmp-junk.c \
contrib/utmp.c \
contrib/ \
COPYING.LIB \
README.top \
$(sysconf_DATA)
procpsngdir = $(docdir)
dist_procpsng_DATA = \
BUGS \
FAQ \
README.top

View File

@ -142,6 +142,12 @@ if test "x$with_ncurses" != xno; then
fi
AC_SUBST([NCURSES_LIBS])
AC_ARG_ENABLE([kill],
AS_HELP_STRING([--disable-kill], [do not build kill]),
[], enable_kill=yes
)
AM_CONDITIONAL(BUILD_KILL, test "x$enable_kill" = xyes)
AC_ARG_ENABLE([oomem],
AS_HELP_STRING([--enable-oomem], [add out-of-memory fields to the library and top]),
[], enable_oomem=no
@ -150,6 +156,14 @@ if test "x$enable_oomem" = xyes; then
AC_DEFINE(OOMEM_ENABLE, 1, [add out-of-memory fields to the library and top])
fi
AC_ARG_ENABLE([w-from],
AS_HELP_STRING([--enable-w-from], [enable w from field by default]),
[], enable_w_from=no
)
if test "x$enable_w_from" = xyes; then
AC_DEFINE(W_SHOWFROM, 1, [enable w from field by default])
fi
AC_CONFIG_FILES([
Makefile
proc/Makefile

View File

@ -0,0 +1,312 @@
See http://www.freelists.org/post/procps/Scan-results,5
based on:
filtered-with-patches.err
these are the categories i've assigned:
defect_was_fixed
EVALUATION_ORDER
pmap
TAINTED_STRING
tload
possibly_filter_out_?
MISSING_BREAK
slabtop
ps/output
avoidable_false_positive
DEADCODE
proc/readproc
FORWARD_NULL
top
vmstat
RESOURCE_LEAK
ps/parser (3)
STRING_NULL
pwdx
proc/readproc
TAINTED_SCALAR
pgrep
slabtop
top (3)
TAINTED_STRING
watch (2)
TOCTOU
sysctl (2)
UNINIT
ps/output (2)
unavoidable_false_positive_?
UNREACHABLE
ps/sortformat
unavoidable_false_positive_but_patched_anyway
OVERRUN_STATIC
top (no defect, but i yield)
pgrep ------------------------------------------------------------------------
Error: TAINTED_SCALAR:
agree that argv might be tainted
but the (int)argv[1][1] index is being passed to isdigit() function (and glibc safely indexes into array sized at 384 bytes)
my_category: avoidable_false_positive (out of step with current glibc implementation)
pgrep.c:720: tainted_data: Passing tainted variable "argv" to a tainted sink.
pgrep.c:558: data_index: Using tainted variable "(int)argv[1][1]" as an index to pointer "*__ctype_b_loc()".
pmap -------------------------------------------------------------------------
Error: EVALUATION_ORDER:
agree that there is a problem.
moreover, it deals with an undocumented command line argument (but sami has documentation addition pending)
a deference was added in line with intent, hopefully avoids this warning
my_category: defect_was_fixed
pmap.c:314: write_write_order: In "arg2 = (arg2 ? arg2++ : arg1)", "arg2" is written in "arg2" (the assignment left-hand side) and written in "arg2 ? arg2++ : arg1" but the order in which the side effects take place is undefined because there is no intervening sequence point.
pwdx -------------------------------------------------------------------------
Error: STRING_NULL:
static buffer is initialized to 0
it is +1 larger than size passed to readlink
was fixed in previous analysis
my_category: avoidable_false_positive
pwdx.c:86: string_null_argument: Function "readlink" does not terminate string "*buf".
pwdx.c:73: var_assign_var: Assigning: "s" = "buf". Both now point to the same unterminated string.
pwdx.c:73: var_assign_var: Assigning: "s" = "buf". Both now point to the same unterminated string.
pwdx.c:73: var_assign_var: Assigning: "s" = "buf". Both now point to the same unterminated string.
pwdx.c:92: string_null: Passing unterminated string "s" to "printf".
slabtop ----------------------------------------------------------------------
Error: MISSING_BREAK:
intentional fall through after setting return code
no change made
my_category: possibly_filter_out_?
slabtop.c:314: unterminated_case: This case (value 104) is not terminated by a 'break' statement.
slabtop.c:316: fallthrough: The above case falls through to this one.
Error: TAINTED_SCALAR:
read limited to single byte signed 'char'
ultimately passed to toupper() function (and glibc safely indexes into array sized at 384 bytes)
my_category: avoidable_false_positive (out of step with current glibc implementation)
slabtop.c:387: tainted_data_argument: Calling function "read" taints argument "c".
slabtop.c:389: tainted_data: Passing tainted variable "c" to a tainted sink.
slabtop.c:233: data_index: Using tainted variable "(int)c" as an index to pointer "*__ctype_toupper_loc()".
sysctl -----------------------------------------------------------------------
Error: TOCTOU:
the pathlength between these two events cannot be reduced further
instead of assessing intervening lines of code, perhaps tool should assess 'if' statements (2)
my_category: avoidable_false_positive
sysctl.c:149: fs_check_call: Calling function "stat" to perform check on "tmpname".
sysctl.c:168: toctou: Calling function "fopen" that uses "tmpname" after a check function. This can cause a time-of-check, time-of-use race condition.
Error: TOCTOU:
the pathlength between these two events cannot be reduced further
instead of assessing intervening lines of code, perhaps tool should assess 'if' statements (2)
my_category: avoidable_false_positive
sysctl.c:327: fs_check_call: Calling function "stat" to perform check on "tmpname".
sysctl.c:345: toctou: Calling function "fopen" that uses "tmpname" after a check function. This can cause a time-of-check, time-of-use race condition.
tload ------------------------------------------------------------------------
Error: TAINTED_STRING:
altered perror call to provide an untainted string
my_category: defect_was_fixed
tload.c:89: tainted_string: Passing tainted string "argv[optind]" to a function that cannot accept tainted data.
top --------------------------------------------------------------------------
Error: FORWARD_NULL:
cpus cannot be NULL without fp also being NULL
the very next 'if (!fp)' ensures cpus will be allocated
my_category: avoidable_false_positive
top.c:1790: assign_zero: Assigning: "cpus" = 0.
top.c:1807: var_deref_op: Dereferencing null variable "cpus".
Error: OVERRUN_STATIC:
This "error" is centered around the following code:
f = w->pflgsall[i + w->begpflg];
w->procflgs[i] = f;
#ifndef USE_X_COLHDR
if (P_MAXPFLGS < f) continue;
#endif
h = Fieldstab[f].head;
The enum P_MAXPFLGS is strictly a fencepost and can *never* appear in the arrays pflgsall or procflgs.
Thus it (39th element) cannot be used in referencing Fieldstab.
However, two enums of higher value (X_XON=40 and X_XOF=41) *can* appear in those arrays.
But the test against the fencepost ensures that those two enums are *never* used in referencing Fieldstab.
When the analyzer sees the conditional using '<' and not '<=' it reports a false positive.
i'm tired of explaining this so the program was changed to accommodate the tool's deficiency
my_category: unavoidable_false_positive_but_patched_anyway
top.c:1417: overrun-local: Overrunning static array "Fieldstab", with 39 elements, at position 39 with index variable "f".
Error: TAINTED_SCALAR:
the index is used subordinate to a case statement ensuring a value between '1' and '4'
my_category: avoidable_false_positive
top.c:2442: tainted_data_argument: Calling function "chin" taints argument "ch".
top.c:848: tainted_data_argument: Calling function "read" taints parameter "*buf".
top.c:2452: tainted_data: Using tainted variable "ch - 49" as an index into an array "Winstk".
Error: TAINTED_SCALAR:
the index is used subordinate to as case statement ensuring a value between '1' and '4'
my_category: avoidable_false_positive
top.c:2719: tainted_data_argument: Calling function "chin" taints argument "ch".
top.c:848: tainted_data_argument: Calling function "read" taints parameter "*buf".
top.c:2720: tainted_data: Passing tainted variable "ch" to a tainted sink.
top.c:2452: data_index: Using tainted variable "ch - 49" as an index to array "Winstk".
Error: TAINTED_SCALAR:
buf tainted by chin is zero terminated
single char is ultimately passed to isprintf() function (and glibc safely indexes into array sized at 384 bytes)
my_category: avoidable_false_positive (out of step with current glibc implementation)
top.c:972: tainted_data_return: Function "keyin" returns tainted data.
top.c:912: tainted_data_argument: Function "chin" taints argument "buf".
top.c:848: tainted_data_argument: Calling function "read" taints parameter "*buf".
top.c:926: return_tainted_data: Returning tainted variable "buf[0]".
top.c:972: var_assign: Assigning: "key" = "keyin", which taints "key".
top.c:1001: tainted_data: Using tainted variable "(int)key" as an index to pointer "*__ctype_b_loc()".
vmstat -----------------------------------------------------------------------
Error: FORWARD_NULL:
partition made non-null with optarg for -p where statMode |= PARTITIONSTAT
if no optarg then program exits with usage
thus call to diskpartition_format will be with non-null pointer
my_category: avoidable_false_positive
vmstat.c:593: assign_zero: Assigning: "partition" = 0.
vmstat.c:669: var_deref_model: Passing null variable "partition" to function "diskpartition_format", which dereferences it.
vmstat.c:301: deref_parm_in_call: Function "strcmp" dereferences parameter "partition_name". (The dereference is assumed on the basis of the 'nonnull' parameter attribute.)
watch ------------------------------------------------------------------------
Error: TAINTED_STRING:
even though the environment variable COLUMNS might begin tainted, from my analysis, the tool is totally mistaken
strtol actually untaints data in the form of 't' and 'endptr' then the environment variable COLUMNS is potentially purified with -1
my_category: avoidable_false_positive
watch.c:95: tainted_string_return_content: "getenv" returns tainted string content.
watch.c:95: var_assign: Assigning: "s" = "getenv("COLUMNS")", which taints "s".
watch.c:100: tainted_data_transitive: Call to function "strtol" with tainted argument "s" returns tainted data.
watch.c:100: var_assign: Assigning: "t" = "strtol(s, &endptr, 0)", which taints "t".
watch.c:101: var_assign_var: Assigning: "incoming_cols" = "(int)t". Both are now tainted.
watch.c:102: var_assign_var: Assigning: "width" = "incoming_cols". Both are now tainted.
watch.c:103: vararg_transitive: Call to "snprintf" with tainted argument "width" taints "env_col_buf".
watch.c:104: tainted_string: Passing tainted string "env_col_buf" to a function that cannot accept tainted data.
Error: TAINTED_STRING:
even though the environment variable LINES might begin tainted, from my analysis, the tool is totally mistaken
strtol actually untaints data in the form of 't' and 'endptr' then the environment variable LINES is potentially purified with -1
my_category: avoidable_false_positive
watch.c:108: tainted_string_return_content: "getenv" returns tainted string content.
watch.c:108: var_assign: Assigning: "s" = "getenv("LINES")", which taints "s".
watch.c:113: tainted_data_transitive: Call to function "strtol" with tainted argument "s" returns tainted data.
watch.c:113: var_assign: Assigning: "t" = "strtol(s, &endptr, 0)", which taints "t".
watch.c:114: var_assign_var: Assigning: "incoming_rows" = "(int)t". Both are now tainted.
watch.c:115: var_assign_var: Assigning: "height" = "incoming_rows". Both are now tainted.
watch.c:116: vararg_transitive: Call to "snprintf" with tainted argument "height" taints "env_row_buf".
watch.c:117: tainted_string: Passing tainted string "env_row_buf" to a function that cannot accept tainted data.
proc/readproc ----------------------------------------------------------------
Error: DEADCODE:
the tool does not understand gperf and the pseudo case labels preceded by goto
the following code snippets illustrate the deficiency:
goto *(&&base + entry.offset);
...
case_Threads:
Threads = strtol(S,&S,10);
continue;
my_category: avoidable_false_positive
proc/readproc.c:387: dead_error_condition: On this path, the condition "Threads" cannot be true.
proc/readproc.c:115: const: After this line, the value of "Threads" is equal to 0.
proc/readproc.c:115: assignment: Assigning: "Threads" = "0L".
proc/readproc.c:388: dead_error_begin: Execution cannot reach this statement "P->nlwp = Threads;".
Error: STRING_NULL:
read is asked to retrieve -1 bytes than passed capacity: num_read = read(fd, ret, cap - 1);
file2str does indeed null terminate sbuf: ret[num_read] = '\0';
my_category: avoidable_false_positive
proc/readproc.c:1193: string_null_argument: Function "file2str" does not terminate string "*sbuf".
proc/readproc.c:514: string_null_argument: Function "read" fills array "*ret" with a non-terminated string.
proc/readproc.c:1197: string_null: Passing unterminated string "sbuf" to a function expecting a null-terminated string.
proc/readproc.c:447: string_null_sink_parm_call: Passing parameter "S" to "strchr" which expects a null-terminated string.
ps/output --------------------------------------------------------------------
Error: MISSING_BREAK:
intentional fall through
my_category: possibly_filter_out_?
ps/output.c:1983: unterminated_default: The default case is not terminated by a 'break' statement.
ps/output.c:1984: fallthrough: The above case falls through to this one.
Error: UNINIT:
the first member is initialized in the very next statement, sufficient for bsearch callback
key.spec = findme;
my_category: avoidable_false_positive
ps/output.c:1737: var_decl: Declaring variable "key" without initializer.
ps/output.c:1739: uninit_use_in_call: Using uninitialized value "key": field "key".flags is uninitialized when calling "bsearch".
Error: UNINIT:
the first member is initialized in the very next statement, sufficient for bsearch callback
key.spec = findme;
my_category: avoidable_false_positive
ps/output.c:1745: var_decl: Declaring variable "key" without initializer.
ps/output.c:1747: uninit_use_in_call: Using uninitialized value "key": field "key".head is uninitialized when calling "bsearch".
ps/parser --------------------------------------------------------------------
Error: RESOURCE_LEAK:
intentional omission
abexit shortly
my_category: avoidable_false_positive
ps/parser.c:1021: alloc_fn: Calling allocation function "malloc".
ps/parser.c:1021: var_assign: Assigning: "pidnode" = storage returned from "malloc(sizeof (selection_node) /*24*/)".
ps/parser.c:1041: leaked_storage: Variable "pidnode" going out of scope leaks the storage it points to.
ps/parser.c:1062: leaked_storage: Variable "pidnode" going out of scope leaks the storage it points to.
Error: RESOURCE_LEAK:
intentional omission
abexit shortly
my_category: avoidable_false_positive
ps/parser.c:1025: alloc_fn: Calling allocation function "malloc".
ps/parser.c:1025: var_assign: Assigning: "grpnode" = storage returned from "malloc(sizeof (selection_node) /*24*/)".
ps/parser.c:1041: leaked_storage: Variable "grpnode" going out of scope leaks the storage it points to.
ps/parser.c:1062: leaked_storage: Variable "grpnode" going out of scope leaks the storage it points to.
Error: RESOURCE_LEAK:
intentional omission
abexit shortly
my_category: avoidable_false_positive
ps/parser.c:1029: alloc_fn: Calling allocation function "malloc".
ps/parser.c:1029: var_assign: Assigning: "sidnode" = storage returned from "malloc(sizeof (selection_node) /*24*/)".
ps/parser.c:1041: leaked_storage: Variable "sidnode" going out of scope leaks the storage it points to.
ps/parser.c:1062: leaked_storage: Variable "sidnode" going out of scope leaks the storage it points to.
ps/sortformat ----------------------------------------------------------------
Error: UNREACHABLE:
the tool does not understand the following 'label' usage (nor do i - perhaps some obscure compiler/platform warning/quirk)
goto unknown;
...
if(0) unknown: err=errbuf;
my_category: unavoidable_false_positive_?
ps/sortformat.c:312: unreachable: This code cannot be reached: "if (0){
unknown:
err = ...".

16
pgrep.c
View File

@ -193,19 +193,22 @@ static union el *read_pidfile(void)
int fd;
struct stat sbuf;
char *endp;
int pid;
int n, pid;
union el *list = NULL;
fd = open(opt_pidfile, O_RDONLY|O_NOCTTY|O_NONBLOCK);
if(fd<0)
goto out;
goto just_ret;
if(fstat(fd,&sbuf) || !S_ISREG(sbuf.st_mode) || sbuf.st_size<1)
goto out;
// type of lock, if any, is not standardized on Linux
if(opt_lock && !has_flock(fd) && !has_fcntl(fd))
goto out;
goto out;
memset(buf,'\0',sizeof buf);
buf[read(fd,buf+1,sizeof buf-2)] = '\0';
n = read(fd,buf+1,sizeof buf-2);
if (n<1)
goto out;
buf[n] = '\0';
pid = strtoul(buf+1,&endp,10);
if(endp<=buf+1 || pid<1 || pid>0x7fffffff)
goto out;
@ -216,6 +219,7 @@ static union el *read_pidfile(void)
list[1].num = pid;
out:
close(fd);
just_ret:
return list;
}
@ -376,6 +380,7 @@ static PROCTAB *do_openproc (void)
}
flags |= PROC_UID;
ptp = openproc (flags, uids, num);
free(uids);
} else {
ptp = openproc (flags);
}
@ -404,6 +409,7 @@ static regex_t * do_regcomp (void)
}
re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case);
free(re);
if (re_err) {
regerror (re_err, preg, errbuf, sizeof(errbuf));
fputs(errbuf,stderr);
@ -530,8 +536,8 @@ static union el * select_procs (int *num)
memset (&task, 0, sizeof (task));
}
closeproc (ptp);
*num = matches;
free(preg);
return list;
}

2
pmap.c
View File

@ -311,7 +311,7 @@ int main(int argc, char *argv[]){
char *arg2 = strchr(arg1,',');
if(arg2)
*arg2 = '\0';
arg2 = arg2 ? arg2++ : arg1;
arg2 = *arg2 ? arg2++ : arg1;
if(*arg1)
range_low = STRTOUKL(arg1,&arg1,16);

View File

@ -1112,15 +1112,13 @@ next_proc:
}
next_task:
for (;;) {
// fills in our path, plus x->tid and x->tgid
if ((!(PT->taskfinder(PT,&skel_p,x,path))) // simple_nexttid
|| (!(ret = PT->taskreader(PT,new_p,x,path)))) { // simple_readtask
goto next_proc;
}
if (!new_p) new_p = ret;
return ret;
// fills in our path, plus x->tid and x->tgid
if ((!(PT->taskfinder(PT,&skel_p,x,path))) // simple_nexttid
|| (!(ret = PT->taskreader(PT,new_p,x,path)))) { // simple_readtask
goto next_proc;
}
if (!new_p) new_p = ret;
return ret;
end_procs:
if (!saved_x) free(x);
@ -1152,7 +1150,7 @@ PROCTAB* openproc(int flags, ...) {
PT->finder = listed_nextpid;
}else{
PT->procfs = opendir("/proc");
if(!PT->procfs) return NULL;
if(!PT->procfs) { free(PT); return NULL; }
PT->finder = simple_nextpid;
}
PT->flags = flags;

View File

@ -214,7 +214,7 @@ void pretty_print_signals(void){
while(++i <= number_of_signals){
int n;
n = printf("%2d %s", i, signal_number_to_name(i));
if(i%7) printf(" \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n);
if(n>0 && i%7) printf(" \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n);
else printf("\n");
}
if((i-1)%7) printf("\n");

View File

@ -312,11 +312,13 @@ int get_slabinfo(struct slab_info **list, struct slab_stat *stats)
if (!fgets(buffer, SLABINFO_VER_LEN, slabfile)) {
fprintf(stderr, "cannot read from slabinfo\n");
free(slabfile);
return 1;
}
if (sscanf(buffer, "slabinfo - version: %d.%d", &major, &minor) != 2) {
fprintf(stderr, "not the good old slabinfo we know\n");
free(slabfile);
return 1;
}
@ -328,6 +330,7 @@ int get_slabinfo(struct slab_info **list, struct slab_stat *stats)
ret = parse_slabinfo10(list, stats, slabfile);
else {
fprintf(stderr, "unrecognizable slabinfo version\n");
free(slabfile);
return 1;
}

View File

@ -856,8 +856,8 @@ unsigned int getdiskstat(struct disk_stat **disks, struct partition_stat **parti
break;
}
fields = sscanf(buff, " %*d %*d %*s %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u", &dummy);
(*disks) = realloc(*disks, (cDisk+1)*sizeof(struct disk_stat));
if (fields == 1){
(*disks) = realloc(*disks, (cDisk+1)*sizeof(struct disk_stat));
sscanf(buff, " %*d %*d %15s %u %u %llu %u %u %u %llu %u %u %u %u",
//&disk_major,
//&disk_minor,

View File

@ -379,7 +379,7 @@ static void prep_forest_sort(void){
if(!sort_list) { /* assume start time order */
incoming = search_format_array("start_time");
if(!incoming) fprintf(stderr, "Could not find start_time!\n");
if(!incoming) { fprintf(stderr, "Could not find start_time!\n"); exit(1); }
tmp_list = malloc(sizeof(sort_node));
tmp_list->reverse = 0;
tmp_list->typecode = '?'; /* what was this for? */
@ -390,7 +390,7 @@ static void prep_forest_sort(void){
}
/* this is required for the forest option */
incoming = search_format_array("ppid");
if(!incoming) fprintf(stderr, "Could not find ppid!\n");
if(!incoming) { fprintf(stderr, "Could not find ppid!\n"); exit(1); }
tmp_list = malloc(sizeof(sort_node));
tmp_list->reverse = 0;
tmp_list->typecode = '?'; /* what was this for? */

View File

@ -119,6 +119,7 @@ static const char *parse_gid(char *str, sel_union *ret){
static const char *parse_cmd(char *str, sel_union *ret){
strncpy(ret->cmd, str, sizeof ret->cmd); // strncpy pads to end
ret->cmd[sizeof(ret->cmd)-1] = '\0'; // but let's be safe
return 0;
}

View File

@ -103,7 +103,7 @@ static void O_wrap(sf_node *sfn, int otype){
endp->next = fnode;
fnode = do_one_spec(trailer,NULL);
if(!fnode)fprintf(stderr,"Seriously crashing. Goodbye cruel world.\n");
if(!fnode) { fprintf(stderr,"Seriously crashing. Goodbye cruel world.\n"); exit(1); }
endp = fnode; while(endp->next) endp = endp->next; /* find end */
endp->next = sfn->f_cooked;
sfn->f_cooked = fnode;

2
pwdx.c
View File

@ -35,7 +35,7 @@ static void version(void)
int main(int argc, char* argv[])
{
char buf[PATH_MAX+1];
static char buf[PATH_MAX+1]; // null terminate string via static
regex_t re;
int i;

15
skill.c
View File

@ -46,8 +46,7 @@ static int saved_argc;
static int sig_or_pri;
static int program;
#define PROG_GARBAGE 0 /* keep this 0 */
static int program = -1;
#define PROG_KILL 1
#define PROG_SKILL 2
/* #define PROG_NICE 3 */ /* easy, but the old one isn't broken */
@ -558,17 +557,13 @@ int main(int argc, const char *argv[]){
tmpstr=strrchr(*argv,'/');
if(tmpstr) tmpstr++;
if(!tmpstr) tmpstr=*argv;
program = PROG_GARBAGE;
if(*tmpstr=='s'){
setpriority(PRIO_PROCESS,my_pid,-20);
if(!strcmp(tmpstr,"snice")) program = PROG_SNICE;
if(!strcmp(tmpstr,"skill")) program = PROG_SKILL;
}else{
if(!strcmp(tmpstr,"kill")) program = PROG_KILL;
}
if(strstr(tmpstr,"kill")) program = PROG_KILL;
if(strstr(tmpstr,"skill")) program = PROG_SKILL;
if(strstr(tmpstr,"snice")) program = PROG_SNICE;
switch(program){
case PROG_SNICE:
case PROG_SKILL:
setpriority(PRIO_PROCESS,my_pid,-20);
skillsnice_parse(argc, argv);
/* show_lists(); */
iterate(); /* this is it, go get them */

View File

@ -87,7 +87,7 @@ int main(int argc, char **argv)
if (argc > optind) {
if ((fd = open(argv[optind], 1)) == -1) {
perror(argv[optind]);
perror("tty");
exit(1);
}
}

45
top.c
View File

@ -714,10 +714,13 @@ static inline void show_scroll (void) {
* what will fit within the current screen width.
* Our special formatting consists of:
* "some text <_delimiter_> some more text <_delimiter_>...\n"
* Where <_delimiter_> is a single byte in the range of:
* \01 through \10 (in decimalizee, 1 - 8)
* and is used to select an 'attribute' from a capabilities table
* which is then applied to the *preceding* substring.
* Where <_delimiter_> is a two bye combination consisting of a
* tilde followed by an ascii digit in the the range of 1 - 8.
* examples: ~1, ~5, ~8, etc.
* The tilde is effectively stripped and the next digit
* converted to an index which is then used to select an
* 'attribute' from a capabilities table. That attribute
* is then applied to the *preceding* substring.
* Once recognized, the delimiter is replaced with a null character
* and viola, we've got a substring ready to output! Strings or
* substrings without delimiters will receive the Cap_norm attribute.
@ -732,24 +735,23 @@ static inline void show_scroll (void) {
* Tabs must always be avoided or our efforts are wasted and
* lines will wrap. To lessen but not eliminate the risk of
* terminfo string truncation, such non-display stuff should
* be placed at the beginning of a "short" line.
* (and as for tabs, gimme 1 more color then no worries, mate) */
* be placed at the beginning of a "short" line. */
static void show_special (int interact, const char *glob) {
/* note: the following is for documentation only,
the real captab is now found in a group's WIN_t !
+------------------------------------------------------+
| char *captab[] = { : Cap's/Delim's |
| Cap_norm, Cap_norm, = \00, \01, |
| cap_bold, capclr_sum, = \02, \03, |
| capclr_msg, capclr_pmt, = \04, \05, |
| capclr_hdr, = \06, |
| capclr_rowhigh, = \07, |
| capclr_rownorm }; = \10 [octal!] |
| Cap_norm, Cap_norm, = \000, \001, |
| cap_bold, capclr_sum, = \002, \003, |
| capclr_msg, capclr_pmt, = \004, \005, |
| capclr_hdr, = \006, |
| capclr_rowhigh, = \007, |
| capclr_rownorm }; = \010 [octal!] |
+------------------------------------------------------+ */
/* ( pssst, after adding the termcap transitions, row may )
( exceed 300+ bytes, even in an 80x24 terminal window! ) */
char tmp[SMLBUFSIZ], lin[MEDBUFSIZ], row[LRGBUFSIZ];
char *rp, *cap, *lin_end, *sub_beg, *sub_end;
char *rp, *lin_end, *sub_beg, *sub_end;
int room;
// handle multiple lines passed in a bunch
@ -763,16 +765,17 @@ static void show_special (int interact, const char *glob) {
*(rp = row) = '\0';
while (*sub_beg) {
switch (*sub_end) {
int ch = *sub_end;
if ('~' == ch) ch = *(sub_end + 1) - '0';
switch (ch) {
case 0: // no end delim, captab makes normal
*(sub_end + 1) = '\0'; // extend str end, then fall through
case 1 ... 8:
cap = Curwin->captab[(int)*sub_end];
*sub_end = '\0';
snprintf(tmp, sizeof(tmp), "%s%.*s%s", cap, room, sub_beg, Caps_off);
snprintf(tmp, sizeof(tmp), "%s%.*s%s", Curwin->captab[ch], room, sub_beg, Caps_off);
rp = scat(rp, tmp);
room -= (sub_end - sub_beg);
sub_beg = ++sub_end;
sub_beg = (sub_end += (ch ? 2 : 1));
break;
default: // nothin' special, just text
++sub_end;
@ -1412,7 +1415,7 @@ static void calibrate_fields (void) {
f = w->pflgsall[i + w->begpflg];
w->procflgs[i] = f;
#ifndef USE_X_COLHDR
if (P_MAXPFLGS < f) continue;
if (P_MAXPFLGS <= f) continue;
#endif
h = Fieldstab[f].head;
// oops, won't fit -- we're outta here...
@ -1463,7 +1466,7 @@ static void calibrate_fields (void) {
w->hdrcaplen += strlen(Caps_off) + strlen(w->capclr_msg);
}
#else
if (P_MAXPFLGS < f) continue;
if (P_MAXPFLGS <= f) continue;
#endif
h = Fieldstab[f].head;
if (P_WCH == f) needpsdb = 1;
@ -3334,8 +3337,8 @@ static void summary_show (void) {
int shift = 0;
/*** hotplug_acclimated ***/
if (kb_main_total > 9999999) { which = "Mb"; shift = 10; }
if (kb_main_total > 9999999999) { which = "Gb"; shift = 20; }
if (kb_main_total > 9999999) { which = "Mb"; shift = 10; }
if (kb_main_total > 9999999999ull) { which = "Gb"; shift = 20; }
show_special(0, fmtmk(MEMORY_twolines
, which, mkM(total), mkM(used), mkM(free), mkM(buffers)

134
top.h
View File

@ -476,63 +476,63 @@ typedef struct WIN_t {
/* Summary Lines specially formatted string(s) --
see 'show_special' for syntax details + other cautions. */
#define LOADAV_line "%s -%s\n"
#define LOADAV_line_alt "%s\06 -%s\n"
#define STATES_line1 "%s:\03" \
" %3u \02total,\03 %3u \02running,\03 %3u \02sleeping,\03 %3u \02stopped,\03 %3u \02zombie\03\n"
#define STATES_line2x4 "%%%s\03" \
" %#5.1f \02user,\03 %#5.1f \02system,\03 %#5.1f \02nice,\03 %#5.1f \02idle\03\n"
#define LOADAV_line_alt "%s~6 -%s\n"
#define STATES_line1 "%s:~3" \
" %3u ~2total,~3 %3u ~2running,~3 %3u ~2sleeping,~3 %3u ~2stopped,~3 %3u ~2zombie~3\n"
#define STATES_line2x4 "%%%s~3" \
" %#5.1f ~2user,~3 %#5.1f ~2system,~3 %#5.1f ~2nice,~3 %#5.1f ~2idle~3\n"
/* These are the STATES_line evolutions
lnx 2.5.x, procps-3.0.5 : IO-wait = i/o wait time
lnx 2.6.x, procps-3.1.12 : IO-wait now wa, hi = hard irq, si = soft irq
lnx 2.7.x, procps-3.2.7 : st = steal time */
#define STATES_line2x5 "%%%s\03" \
" %#5.1f \02user,\03 %#5.1f \02system,\03 %#5.1f \02nice,\03 %#5.1f \02idle,\03 %#5.1f \02IO-wait\03\n"
#define STATES_line2x6 "%%%s\03" \
" %#5.1f \02us,\03 %#5.1f \02sy,\03 %#5.1f \02ni,\03 %#5.1f \02id,\03 %#5.1f \02wa,\03 %#5.1f \02hi,\03 %#5.1f \02si\03\n"
#define STATES_line2x7 "%%%s\03" \
"%#5.1f \02us,\03%#5.1f \02sy,\03%#5.1f \02ni,\03%#5.1f \02id,\03%#5.1f \02wa,\03%#5.1f \02hi,\03%#5.1f \02si,\03%#5.1f \02st\03\n"
#define STATES_line2x5 "%%%s~3" \
" %#5.1f ~2user,~3 %#5.1f ~2system,~3 %#5.1f ~2nice,~3 %#5.1f ~2idle,~3 %#5.1f ~2IO-wait~3\n"
#define STATES_line2x6 "%%%s~3" \
" %#5.1f ~2us,~3 %#5.1f ~2sy,~3 %#5.1f ~2ni,~3 %#5.1f ~2id,~3 %#5.1f ~2wa,~3 %#5.1f ~2hi,~3 %#5.1f ~2si~3\n"
#define STATES_line2x7 "%%%s~3" \
"%#5.1f ~2us,~3%#5.1f ~2sy,~3%#5.1f ~2ni,~3%#5.1f ~2id,~3%#5.1f ~2wa,~3%#5.1f ~2hi,~3%#5.1f ~2si,~3%#5.1f ~2st~3\n"
#define MEMORY_twolines \
"%s Mem: \03 %8lu \02total,\03 %8lu \02used,\03 %8lu \02free,\03 %8lu \02buffers\03\n" \
"%s Swap:\03 %8lu \02total,\03 %8lu \02used,\03 %8lu \02free,\03 %8lu \02cached\03\n"
"%s Mem: ~3 %8lu ~2total,~3 %8lu ~2used,~3 %8lu ~2free,~3 %8lu ~2buffers~3\n" \
"%s Swap:~3 %8lu ~2total,~3 %8lu ~2used,~3 %8lu ~2free,~3 %8lu ~2cached~3\n"
/* Keyboard Help specially formatted string(s) --
see 'show_special' for syntax details + other cautions. */
#define KEYS_help \
"Help for Interactive Commands\02 - %s\n" \
"Window \01%s\06: \01Cumulative mode \03%s\02. \01System\06: \01Delay \03%.1f secs\02; \01Secure mode \03%s\02.\n" \
"Help for Interactive Commands~2 - %s\n" \
"Window ~1%s~6: ~1Cumulative mode ~3%s~2. ~1System~6: ~1Delay ~3%.1f secs~2; ~1Secure mode ~3%s~2.\n" \
"\n" \
" Z\05,\01B\05 Global: '\01Z\02' change color mappings; '\01B\02' disable/enable bold\n" \
" l,t,m Toggle Summaries: '\01l\02' load avg; '\01t\02' task/cpu stats; '\01m\02' mem info\n" \
" 1,I Toggle SMP view: '\0011\02' single/separate states; '\01I\02' Irix/Solaris mode\n" \
" Z~5,~1B~5 Global: '~1Z~2' change color mappings; '~1B~2' disable/enable bold\n" \
" l,t,m Toggle Summaries: '~1l~2' load avg; '~1t~2' task/cpu stats; '~1m~2' mem info\n" \
" 1,I Toggle SMP view: '~11~2' single/separate states; '~1I~2' Irix/Solaris mode\n" \
" f,F Manage Fields: add/remove; change order; select sort field\n" \
"\n" \
" <,> . Move sort field: '\01<\02' next col left; '\01>\02' next col right\n" \
" R,H,V . Toggle: '\01R\02' norm/rev sort; '\01H\02' show threads; '\01V\02' forest view\n" \
" c,i,S . Toggle: '\01c\02' cmd name/line; '\01i\02' idle tasks; '\01S\02' cumulative time\n" \
" x\05,\01y\05 . Toggle highlights: '\01x\02' sort field; '\01y\02' running tasks\n" \
" z\05,\01b\05 . Toggle: '\01z\02' color/mono; '\01b\02' bold/reverse (only if 'x' or 'y')\n" \
" u,U . Show: '\01u\02' effective user; '\01U\02' real, saved, file or effective user\n" \
" <,> . Move sort field: '~1<~2' next col left; '~1>~2' next col right\n" \
" R,H,V . Toggle: '~1R~2' norm/rev sort; '~1H~2' show threads; '~1V~2' forest view\n" \
" c,i,S . Toggle: '~1c~2' cmd name/line; '~1i~2' idle tasks; '~1S~2' cumulative time\n" \
" x~5,~1y~5 . Toggle highlights: '~1x~2' sort field; '~1y~2' running tasks\n" \
" z~5,~1b~5 . Toggle: '~1z~2' color/mono; '~1b~2' bold/reverse (only if 'x' or 'y')\n" \
" u,U . Show: '~1u~2' effective user; '~1U~2' real, saved, file or effective user\n" \
" n or # . Set maximum tasks displayed\n" \
" C,... . Toggle scroll coordinates msg for: \01up\02,\01down\02,\01left\02,right\02,\01home\02,\01end\02\n" \
" C,... . Toggle scroll coordinates msg for: ~1up~2,~1down~2,~1left~2,right~2,~1home~2,~1end~2\n" \
"\n" \
"%s" \
" W Write configuration file\n" \
" q Quit\n" \
" ( commands shown with '.' require a \01visible\02 task display \01window\02 ) \n" \
"Press '\01h\02' or '\01?\02' for help with \01Windows\02,\n" \
" ( commands shown with '.' require a ~1visible~2 task display ~1window~2 ) \n" \
"Press '~1h~2' or '~1?~2' for help with ~1Windows~2,\n" \
"any other key to continue " \
""
/* This guy goes into the help text (maybe) */
#define KEYS_help_unsecured \
" k,r Manipulate tasks: '\01k\02' kill; '\01r\02' renice\n" \
" k,r Manipulate tasks: '~1k~2' kill; '~1r~2' renice\n" \
" d or s Set update interval\n" \
""
/* Fields Management specially formatted string(s) --
see 'show_special' for syntax details + other cautions */
#define FIELDS_heading \
"Fields Management\02 for window \01%s\06, whose current sort field is \01%s\02\n" \
"Fields Management~2 for window ~1%s~6, whose current sort field is ~1%s~2\n" \
" Navigate with Up/Dn, Right selects for move then <Enter> or Left commits,\n" \
" 'd' or <Space> toggles display, 's' sets sort. Use 'q' or <Esc> to end! " \
""
@ -540,58 +540,58 @@ typedef struct WIN_t {
/* Colors Help specially formatted string(s) --
see 'show_special' for syntax details + other cautions. */
#define COLOR_help \
"Help for color mapping\02 - %s\n" \
"current window: \01%s\06\n" \
"Help for color mapping~2 - %s\n" \
"current window: ~1%s~6\n" \
"\n" \
" color - 04:25:44 up 8 days, 50 min, 7 users, load average:\n" \
" Tasks:\03 64 \02total,\03 2 \03running,\03 62 \02sleeping,\03 0 \02stopped,\03\n" \
" %%Cpu(s):\03 76.5 \02user,\03 11.2 \02system,\03 0.0 \02nice,\03 12.3 \02idle\03\n" \
" \01 Nasty Message! \04 -or- \01Input Prompt\05\n" \
" \01 PID TTY PR NI %%CPU TIME+ VIRT SWAP S COMMAND \06\n" \
" 17284 \10pts/2 \07 8 0 0.0 0:00.75 1380 0 S /bin/bash \10\n" \
" \01 8601 pts/1 7 -10 0.4 0:00.03 916 0 R color -b -z\07\n" \
" 11005 \10? \07 9 0 0.0 0:02.50 2852 1008 S amor -sessi\10\n" \
" available toggles: \01B\02 =disable bold globally (\01%s\02),\n" \
" \01z\02 =color/mono (\01%s\02), \01b\02 =tasks \"bold\"/reverse (\01%s\02)\n" \
" Tasks:~3 64 ~2total,~3 2 ~3running,~3 62 ~2sleeping,~3 0 ~2stopped,~3\n" \
" %%Cpu(s):~3 76.5 ~2user,~3 11.2 ~2system,~3 0.0 ~2nice,~3 12.3 ~2idle~3\n" \
" ~1 Nasty Message! ~4 -or- ~1Input Prompt~5\n" \
" ~1 PID TTY PR NI %%CPU TIME+ VIRT SWAP S COMMAND ~6\n" \
" 17284 ~8pts/2 ~7 8 0 0.0 0:00.75 1380 0 S /bin/bash ~8\n" \
" ~1 8601 pts/1 7 -10 0.4 0:00.03 916 0 R color -b -z~7\n" \
" 11005 ~8? ~7 9 0 0.0 0:02.50 2852 1008 S amor -sessi~8\n" \
" available toggles: ~1B~2 =disable bold globally (~1%s~2),\n" \
" ~1z~2 =color/mono (~1%s~2), ~1b~2 =tasks \"bold\"/reverse (~1%s~2)\n" \
"\n" \
"Select \01target\02 as upper case letter:\n" \
" S\02 = Summary Data,\01 M\02 = Messages/Prompts,\n" \
" H\02 = Column Heads,\01 T\02 = Task Information\n" \
"Select \01color\02 as number:\n" \
" 0\02 = black,\01 1\02 = red, \01 2\02 = green,\01 3\02 = yellow,\n" \
" 4\02 = blue, \01 5\02 = magenta,\01 6\02 = cyan, \01 7\02 = white\n" \
"Select ~1target~2 as upper case letter:\n" \
" S~2 = Summary Data,~1 M~2 = Messages/Prompts,\n" \
" H~2 = Column Heads,~1 T~2 = Task Information\n" \
"Select ~1color~2 as number:\n" \
" 0~2 = black,~1 1~2 = red, ~1 2~2 = green,~1 3~2 = yellow,\n" \
" 4~2 = blue, ~1 5~2 = magenta,~1 6~2 = cyan, ~1 7~2 = white\n" \
"\n" \
"Selected: \01target\02 \01 %c \04; \01color\02 \01 %d \04\n" \
" press 'q' to abort changes to window '\01%s\02'\n" \
"Selected: ~1target~2 ~1 %c ~4; ~1color~2 ~1 %d ~4\n" \
" press 'q' to abort changes to window '~1%s~2'\n" \
" press 'a' or 'w' to commit & change another, <Enter> to commit and end " \
""
/* Windows/Field Group Help specially formatted string(s) --
see 'show_special' for syntax details + other cautions. */
#define WINDOWS_help \
"Help for Windows / Field Groups\02 - \"Current Window\" = \01 %s \06\n" \
"Help for Windows / Field Groups~2 - \"Current Window\" = ~1 %s ~6\n" \
"\n" \
". Use multiple \01windows\02, each with separate config opts (color,fields,sort,etc)\n" \
". The 'current' window controls the \01Summary Area\02 and responds to your \01Commands\02\n" \
" . that window's \01task display\02 can be turned \01Off\02 & \01On\02, growing/shrinking others\n" \
" . with \01NO\02 task display, some commands will be \01disabled\02 ('i','R','n','c', etc)\n" \
" until a \01different window\02 has been activated, making it the 'current' window\n" \
". You \01change\02 the 'current' window by: \01 1\02) cycling forward/backward;\01 2\02) choosing\n" \
" a specific field group; or\01 3\02) exiting the color mapping or fields screens\n" \
". Commands \01available anytime -------------\02\n" \
" A . Alternate display mode toggle, show \01Single\02 / \01Multiple\02 windows\n" \
". Use multiple ~1windows~2, each with separate config opts (color,fields,sort,etc)\n" \
". The 'current' window controls the ~1Summary Area~2 and responds to your ~1Commands~2\n" \
" . that window's ~1task display~2 can be turned ~1Off~2 & ~1On~2, growing/shrinking others\n" \
" . with ~1NO~2 task display, some commands will be ~1disabled~2 ('i','R','n','c', etc)\n" \
" until a ~1different window~2 has been activated, making it the 'current' window\n" \
". You ~1change~2 the 'current' window by: ~1 1~2) cycling forward/backward;~1 2~2) choosing\n" \
" a specific field group; or~1 3~2) exiting the color mapping or fields screens\n" \
". Commands ~1available anytime -------------~2\n" \
" A . Alternate display mode toggle, show ~1Single~2 / ~1Multiple~2 windows\n" \
" g . Choose another field group and make it 'current', or change now\n" \
" by selecting a number from: \01 1\02 =%s;\01 2\02 =%s;\01 3\02 =%s; or\01 4\02 =%s\n" \
". Commands \01requiring\02 '\01A\02' mode\01 -------------\02\n" \
" G . Change the \01Name\05 of the 'current' window/field group\n" \
" \01*\04 a , w . Cycle through all four windows: '\01a\05' Forward; '\01w\05' Backward\n" \
" \01*\04 - , _ . Show/Hide: '\01-\05' \01Current\02 window; '\01_\05' all \01Visible\02/\01Invisible\02\n" \
" by selecting a number from: ~1 1~2 =%s;~1 2~2 =%s;~1 3~2 =%s; or~1 4~2 =%s\n" \
". Commands ~1requiring~2 '~1A~2' mode~1 -------------~2\n" \
" G . Change the ~1Name~5 of the 'current' window/field group\n" \
" ~1*~4 a , w . Cycle through all four windows: '~1a~5' Forward; '~1w~5' Backward\n" \
" ~1*~4 - , _ . Show/Hide: '~1-~5' ~1Current~2 window; '~1_~5' all ~1Visible~2/~1Invisible~2\n" \
" The screen will be divided evenly between task displays. But you can make\n" \
" some \01larger\02 or \01smaller\02, using '\01n\02' and '\01i\02' commands. Then later you could:\n" \
" \01*\04 = , + . Rebalance tasks: '\01=\05' \01Current\02 window; '\01+\05' \01Every\02 window\n" \
" (this also forces the \01current\02 or \01every\02 window to become visible)\n" \
" some ~1larger~2 or ~1smaller~2, using '~1n~2' and '~1i~2' commands. Then later you could:\n" \
" ~1*~4 = , + . Rebalance tasks: '~1=~5' ~1Current~2 window; '~1+~5' ~1Every~2 window\n" \
" (this also forces the ~1current~2 or ~1every~2 window to become visible)\n" \
"\n" \
"In '\01A\02' mode, '\01*\04' keys are your \01essential\02 commands. Please try the '\01a\02' and '\01w\02'\n" \
"In '~1A~2' mode, '~1*~4' keys are your ~1essential~2 commands. Please try the '~1a~2' and '~1w~2'\n" \
"commands plus the 'g' sub-commands NOW. Press <Enter> to make 'Current' " \
""

View File

@ -303,6 +303,8 @@ static int diskpartition_format(const char* partition_name){
}
}
if(!current_partition){
free(disks);
free(partitions);
return -1;
}
diskpartition_header(partition_name);
@ -323,6 +325,8 @@ static int diskpartition_format(const char* partition_name){
}
}
if(!current_partition){
free(disks);
free(partitions);
return -1;
}
printf (format,
@ -422,7 +426,7 @@ static void slabformat (void){
fSlab=fopen("/proc/slabinfo", "rb");
if(!fSlab){
fprintf(stderr, "Your kernel doesn't support slabinfo.\n");
fprintf(stderr, "Your kernel doesn't support slabinfo or your permissions are insufficient.\n");
return;
}
@ -454,6 +458,7 @@ static void slabformat (void){
}
free(slabs);
}
free(fSlab);
}
////////////////////////////////////////////////////////////////////////////