pmap: fixing broken indentation in the -X/-XX modes

This commit changes the processing principle of the -X/-XX modes
from 1-pass to 2-pass. A separate width measurement stage has been
added, so that the real maximum widths can be measured and used
for correct indentation.

The firstmapping variable now has a new value (2) used for the
width measurement stage (1st pass). The printing is disabled
in this stage. The file position is reset to the beginning
of the file once the end of file is reached and the printing stage
(2nd pass) begins.
It's questionable if this approach is sensitive to Read-after-Write
race conditions. Anyway, this feature is a good candidate for
a complete redesign in the future.

Additionally this commit introduces a final cleaning of the list
used for the evaluation of totals in the -X/-XX modes.
This commit is contained in:
Jaromir Capik 2013-02-06 23:01:54 +01:00
parent ca76af22ca
commit 20ce346ebd

92
pmap.c
View File

@ -184,7 +184,7 @@ struct listnode {
struct listnode *next;
};
static struct listnode *listhead=NULL, *listtail=NULL;
static struct listnode *listhead=NULL, *listtail=NULL, *listnode;
static int is_unimportant (char *s)
@ -201,7 +201,6 @@ static int is_unimportant (char *s)
static void print_extended_maps (FILE *f)
{
struct listnode *listnode;
char flags[DETAIL_LENGTH], map_desc[128],
detail_desc[DETAIL_LENGTH], value_str[NUM_LENGTH],
start[NUM_LENGTH], end[NUM_LENGTH],
@ -216,7 +215,7 @@ static void print_extended_maps (FILE *f)
char has_vmflags = 0;
ret = fgets(mapbuf, sizeof mapbuf, f);
firstmapping = 1;
firstmapping = 2;
while (ret != NULL) {
/* === READ MAPPING === */
map_desc[0] = '\0';
@ -254,7 +253,7 @@ static void print_extended_maps (FILE *f)
goto loop_end;
/* === CREATE LIST AND FILL description FIELD === */
if (listnode == NULL) {
assert(firstmapping == 1);
assert(firstmapping == 2);
listnode = calloc(1, sizeof *listnode);
if (listhead == NULL) {
assert(listtail == NULL);
@ -271,15 +270,14 @@ static void print_extended_maps (FILE *f)
listnode->max_width = 7;
} else {
/* === LIST EXISTS === */
if ((listnode == NULL) ||
(strcmp(listnode->description, detail_desc) != 0))
if (strcmp(listnode->description, detail_desc) != 0)
xerrx(EXIT_FAILURE, "ERROR: %s %s",
_("inconsistent detail field in smaps file, line:\n"),
mapbuf);
}
strcpy(listnode->value_str, value_str);
sscanf(value_str, "%"KLF"u", &listnode->value);
listnode->total += listnode->value;
if (firstmapping == 2) listnode->total += listnode->value;
if (strlen(value_str) > listnode->max_width)
listnode->max_width = strlen(value_str);
listnode = listnode->next;
@ -297,51 +295,60 @@ loop_end:
if (strlen(vmflags) > maxwv) maxwv = strlen(vmflags);
}
/* === PRINT THIS MAPPING === */
/* Print header */
if (firstmapping && !q_option) {
if (strlen("Address") > maxw1) maxw1 = strlen("Address");
if (strlen("Flags") > maxw2) maxw2 = strlen("Flags");
if (strlen("Offset") > maxw3) maxw3 = strlen("Offset");
if (strlen("Device") > maxw4) maxw4 = strlen("Device");
if (strlen("Inode") > maxw5) maxw5 = strlen("Inode");
if (has_vmflags && strlen("VmFlags") > maxwv) maxwv = strlen("VmFlags");
if (firstmapping == 2) { /* width measurement stage, do not print anything yet */
if (ret == NULL) { /* once the end of file is reached ...*/
firstmapping = 1; /* ... we reset the file position to the beginning of the file */
fseek(f, 0, SEEK_SET); /* ... and repeat the process with printing enabled */
ret = fgets(mapbuf, sizeof mapbuf, f); /* this is not ideal and needs to be redesigned one day */
}
} else { /* the maximum widths have been measured, we've already reached the printing stage */
/* === PRINT THIS MAPPING === */
/* Print header */
if (firstmapping && !q_option) {
if (strlen("Address") > maxw1) maxw1 = strlen("Address");
if (strlen("Flags") > maxw2) maxw2 = strlen("Flags");
if (strlen("Offset") > maxw3) maxw3 = strlen("Offset");
if (strlen("Device") > maxw4) maxw4 = strlen("Device");
if (strlen("Inode") > maxw5) maxw5 = strlen("Inode");
if (has_vmflags && strlen("VmFlags") > maxwv) maxwv = strlen("VmFlags");
sprintf(fmt_str, "%%%ds %%%ds %%%ds %%%ds %%%ds",
maxw1, maxw2, maxw3, maxw4, maxw5);
printf(fmt_str, "Address", "Flags", "Offset", "Device", "Inode");
for (listnode=listhead; listnode=listnode->next;
listnode!=NULL) {
sprintf(fmt_str, " %%%ds", listnode->max_width);
printf(fmt_str, listnode->description);
}
if (has_vmflags) {
sprintf(fmt_str, " %%%ds", maxwv);
printf(fmt_str, "VmFlags");
}
printf(" %s\n", "Description");
}
/* Print data */
sprintf(fmt_str, "%%%ds %%%ds %%%ds %%%ds %%%ds",
maxw1, maxw2, maxw3, maxw4, maxw5);
printf(fmt_str, "Address", "Flags", "Offset", "Device", "Inode");
printf(fmt_str, start, flags, offset, dev, inode);
for (listnode=listhead; listnode=listnode->next;
listnode!=NULL) {
sprintf(fmt_str, " %%%ds", listnode->max_width);
printf(fmt_str, listnode->description);
printf(fmt_str, listnode->value_str);
}
if (has_vmflags) {
sprintf(fmt_str, " %%%ds", maxwv);
printf(fmt_str, "VmFlags");
printf(fmt_str, vmflags);
}
printf(" %s\n", "Description");
printf(" %s\n", map_desc);
firstmapping = 0;
}
/* Print data */
sprintf(fmt_str, "%%%ds %%%ds %%%ds %%%ds %%%ds",
maxw1, maxw2, maxw3, maxw4, maxw5);
printf(fmt_str, start, flags, offset, dev, inode);
for (listnode=listhead; listnode=listnode->next;
listnode!=NULL) {
sprintf(fmt_str, " %%%ds", listnode->max_width);
printf(fmt_str, listnode->value_str);
}
if (has_vmflags) {
sprintf(fmt_str, " %%%ds", maxwv);
printf(fmt_str, vmflags);
}
printf(" %s\n", map_desc);
firstmapping = 0;
}
/* === PRINT TOTALS === */
if (!q_option && listhead!=NULL) {
@ -722,6 +729,13 @@ int main(int argc, char **argv)
closeproc(PT);
free(pidlist);
/* cleaning the list used for the -X/-XX modes */
for (listnode = listhead; listnode != NULL ; ) {
listnode = listnode -> next;
free(listhead);
listhead = listnode;
}
if (count)
/* didn't find all processes asked for */
ret |= 42;