Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
htop
Commits
d2acffa5
Commit
d2acffa5
authored
Mar 15, 2015
by
Hisham Muhammad
Browse files
Merge branch 'wip' of
https://github.com/hishamhm/htop
into freebsd
Conflicts: htop.c unsupported/Platform.h
parents
c29e53c5
50000d80
Changes
60
Hide whitespace changes
Inline
Side-by-side
Settings.c
View file @
d2acffa5
...
@@ -18,64 +18,138 @@ in the source distribution for its full text.
...
@@ -18,64 +18,138 @@ in the source distribution for its full text.
#define DEFAULT_DELAY 15
#define DEFAULT_DELAY 15
/*{
/*{
#include "ProcessList.h"
#include "Process.h"
#include "Header.h"
#include <stdbool.h>
#include <stdbool.h>
typedef struct {
int len;
char** names;
int* modes;
} MeterColumnSettings;
typedef struct Settings_ {
typedef struct Settings_ {
char* userSettings;
char* filename;
ProcessList* pl;
Header* header;
MeterColumnSettings columns[2];
ProcessField* fields;
int flags;
int colorScheme;
int colorScheme;
int delay;
int delay;
int direction;
ProcessField sortKey;
bool countCPUsFromZero;
bool detailedCPUTime;
bool treeView;
bool hideThreads;
bool shadowOtherUsers;
bool showThreadNames;
bool hideKernelThreads;
bool hideUserlandThreads;
bool highlightBaseName;
bool highlightMegabytes;
bool highlightThreads;
bool updateProcessNames;
bool accountGuestInCPUMeter;
bool headerMargin;
bool changed;
bool changed;
} Settings;
} Settings;
#ifndef Settings_cpuId
#define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromZero ? (cpu) : (cpu)+1)
#endif
}*/
}*/
static
ProcessField
defaultFields
[]
=
{
PID
,
USER
,
PRIORITY
,
NICE
,
M_SIZE
,
M_RESIDENT
,
M_SHARE
,
STATE
,
PERCENT_CPU
,
PERCENT_MEM
,
TIME
,
COMM
,
0
};
//static ProcessField defaultIoFields[] = { PID, IO_PRIORITY, USER, IO_READ_RATE, IO_WRITE_RATE, IO_RATE, COMM, 0 };
void
Settings_delete
(
Settings
*
this
)
{
void
Settings_delete
(
Settings
*
this
)
{
free
(
this
->
userSettings
);
free
(
this
->
filename
);
free
(
this
->
fields
);
for
(
unsigned
int
i
=
0
;
i
<
(
sizeof
(
this
->
columns
)
/
sizeof
(
MeterColumnSettings
));
i
++
)
{
String_freeArray
(
this
->
columns
[
i
].
names
);
free
(
this
->
columns
[
i
].
modes
);
}
free
(
this
);
free
(
this
);
}
}
static
void
Settings_readMeters
(
Settings
*
this
,
char
*
line
,
HeaderSide
side
)
{
static
void
Settings_readMeters
(
Settings
*
this
,
char
*
line
,
int
column
)
{
char
*
trim
=
String_trim
(
line
);
char
*
trim
=
String_trim
(
line
);
int
nIds
;
int
nIds
;
char
**
ids
=
String_split
(
trim
,
' '
,
&
nIds
);
char
**
ids
=
String_split
(
trim
,
' '
,
&
nIds
);
free
(
trim
);
free
(
trim
);
for
(
int
i
=
0
;
ids
[
i
];
i
++
)
{
this
->
columns
[
column
].
names
=
ids
;
Header_createMeter
(
this
->
header
,
ids
[
i
],
side
);
}
String_freeArray
(
ids
);
}
}
static
void
Settings_readMeterModes
(
Settings
*
this
,
char
*
line
,
HeaderSide
side
)
{
static
void
Settings_readMeterModes
(
Settings
*
this
,
char
*
line
,
int
column
)
{
char
*
trim
=
String_trim
(
line
);
char
*
trim
=
String_trim
(
line
);
int
nIds
;
int
nIds
;
char
**
ids
=
String_split
(
trim
,
' '
,
&
nIds
);
char
**
ids
=
String_split
(
trim
,
' '
,
&
nIds
);
free
(
trim
);
free
(
trim
);
int
len
=
0
;
for
(
int
i
=
0
;
ids
[
i
];
i
++
)
{
for
(
int
i
=
0
;
ids
[
i
];
i
++
)
{
int
mode
=
atoi
(
ids
[
i
]);
len
++
;
Header_setMode
(
this
->
header
,
i
,
mode
,
side
);
}
this
->
columns
[
column
].
len
=
len
;
int
*
modes
=
calloc
(
len
,
sizeof
(
int
));
for
(
int
i
=
0
;
i
<
len
;
i
++
)
{
modes
[
i
]
=
atoi
(
ids
[
i
]);
}
}
String_freeArray
(
ids
);
String_freeArray
(
ids
);
this
->
columns
[
column
].
modes
=
modes
;
}
}
static
void
Settings_defaultMeters
(
Header
*
header
,
int
cpuCount
)
{
static
void
Settings_defaultMeters
(
Settings
*
this
,
int
cpuCount
)
{
int
sizes
[]
=
{
3
,
3
};
if
(
cpuCount
>
4
)
{
sizes
[
1
]
++
;
}
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
this
->
columns
[
i
].
names
=
calloc
(
sizes
[
i
],
sizeof
(
char
*
));
this
->
columns
[
i
].
modes
=
calloc
(
sizes
[
i
],
sizeof
(
int
));
}
int
r
=
0
;
if
(
cpuCount
>
8
)
{
if
(
cpuCount
>
8
)
{
Header_createMeter
(
header
,
"LeftCPUs2"
,
LEFT_HEADER
);
this
->
columns
[
0
].
names
[
0
]
=
strdup
(
"LeftCPUs2"
);
Header_createMeter
(
header
,
"RightCPUs2"
,
RIGHT_HEADER
);
this
->
columns
[
1
].
names
[
r
++
]
=
strdup
(
"RightCPUs2"
);
}
else
if
(
cpuCount
>
4
)
{
}
else
if
(
cpuCount
>
4
)
{
Header_createMeter
(
header
,
"LeftCPUs"
,
LEFT_HEADER
);
this
->
columns
[
0
].
names
[
0
]
=
strdup
(
"LeftCPUs"
);
Header_createMeter
(
header
,
"RightCPUs"
,
RIGHT_HEADER
);
this
->
columns
[
1
].
names
[
r
++
]
=
strdup
(
"RightCPUs"
);
}
else
{
}
else
{
Header_createMeter
(
header
,
"AllCPUs"
,
LEFT_HEADER
);
this
->
columns
[
0
].
names
[
0
]
=
strdup
(
"AllCPUs"
);
}
this
->
columns
[
0
].
names
[
1
]
=
strdup
(
"Memory"
);
this
->
columns
[
0
].
names
[
2
]
=
strdup
(
"Swap"
);
this
->
columns
[
1
].
names
[
r
++
]
=
strdup
(
"Tasks"
);
this
->
columns
[
1
].
names
[
r
++
]
=
strdup
(
"LoadAverage"
);
this
->
columns
[
1
].
names
[
r
++
]
=
strdup
(
"Uptime"
);
}
static
void
readFields
(
ProcessField
*
fields
,
int
*
flags
,
const
char
*
line
)
{
char
*
trim
=
String_trim
(
line
);
int
nIds
;
char
**
ids
=
String_split
(
trim
,
' '
,
&
nIds
);
free
(
trim
);
int
i
,
j
;
*
flags
=
0
;
for
(
j
=
0
,
i
=
0
;
i
<
LAST_PROCESSFIELD
&&
ids
[
i
];
i
++
)
{
// This "+1" is for compatibility with the older enum format.
int
id
=
atoi
(
ids
[
i
])
+
1
;
if
(
id
>
0
&&
id
<
LAST_PROCESSFIELD
)
{
fields
[
j
]
=
id
;
*
flags
|=
Process_fields
[
id
].
flags
;
j
++
;
}
}
}
Header_createMeter
(
header
,
"Memory"
,
LEFT_HEADER
);
fields
[
j
]
=
(
ProcessField
)
NULL
;
Header_createMeter
(
header
,
"Swap"
,
LEFT_HEADER
);
String_freeArray
(
ids
);
Header_createMeter
(
header
,
"Tasks"
,
RIGHT_HEADER
);
Header_createMeter
(
header
,
"LoadAverage"
,
RIGHT_HEADER
);
Header_createMeter
(
header
,
"Uptime"
,
RIGHT_HEADER
);
}
}
static
bool
Settings_read
(
Settings
*
this
,
const
char
*
fileName
,
int
cpuCount
)
{
static
bool
Settings_read
(
Settings
*
this
,
const
char
*
fileName
,
int
cpuCount
)
{
...
@@ -94,59 +168,43 @@ static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
...
@@ -94,59 +168,43 @@ static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
continue
;
continue
;
}
}
if
(
String_eq
(
option
[
0
],
"fields"
))
{
if
(
String_eq
(
option
[
0
],
"fields"
))
{
char
*
trim
=
String_trim
(
option
[
1
]);
readFields
(
this
->
fields
,
&
(
this
->
flags
),
option
[
1
]);
int
nIds
;
char
**
ids
=
String_split
(
trim
,
' '
,
&
nIds
);
free
(
trim
);
int
i
,
j
;
this
->
pl
->
flags
=
0
;
for
(
j
=
0
,
i
=
0
;
i
<
LAST_PROCESSFIELD
&&
ids
[
i
];
i
++
)
{
// This "+1" is for compatibility with the older enum format.
int
id
=
atoi
(
ids
[
i
])
+
1
;
if
(
id
>
0
&&
id
<
LAST_PROCESSFIELD
)
{
this
->
pl
->
fields
[
j
]
=
id
;
this
->
pl
->
flags
|=
Process_fieldFlags
[
id
];
j
++
;
}
}
this
->
pl
->
fields
[
j
]
=
(
ProcessField
)
NULL
;
String_freeArray
(
ids
);
}
else
if
(
String_eq
(
option
[
0
],
"sort_key"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"sort_key"
))
{
// This "+1" is for compatibility with the older enum format.
// This "+1" is for compatibility with the older enum format.
this
->
pl
->
sortKey
=
atoi
(
option
[
1
])
+
1
;
this
->
sortKey
=
atoi
(
option
[
1
])
+
1
;
}
else
if
(
String_eq
(
option
[
0
],
"sort_direction"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"sort_direction"
))
{
this
->
pl
->
direction
=
atoi
(
option
[
1
]);
this
->
direction
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"tree_view"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"tree_view"
))
{
this
->
pl
->
treeView
=
atoi
(
option
[
1
]);
this
->
treeView
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"hide_threads"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"hide_threads"
))
{
this
->
pl
->
hideThreads
=
atoi
(
option
[
1
]);
this
->
hideThreads
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"hide_kernel_threads"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"hide_kernel_threads"
))
{
this
->
pl
->
hideKernelThreads
=
atoi
(
option
[
1
]);
this
->
hideKernelThreads
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"hide_userland_threads"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"hide_userland_threads"
))
{
this
->
pl
->
hideUserlandThreads
=
atoi
(
option
[
1
]);
this
->
hideUserlandThreads
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"shadow_other_users"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"shadow_other_users"
))
{
this
->
pl
->
shadowOtherUsers
=
atoi
(
option
[
1
]);
this
->
shadowOtherUsers
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"show_thread_names"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"show_thread_names"
))
{
this
->
pl
->
showThreadNames
=
atoi
(
option
[
1
]);
this
->
showThreadNames
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"highlight_base_name"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"highlight_base_name"
))
{
this
->
pl
->
highlightBaseName
=
atoi
(
option
[
1
]);
this
->
highlightBaseName
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"highlight_megabytes"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"highlight_megabytes"
))
{
this
->
pl
->
highlightMegabytes
=
atoi
(
option
[
1
]);
this
->
highlightMegabytes
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"highlight_threads"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"highlight_threads"
))
{
this
->
pl
->
highlightThreads
=
atoi
(
option
[
1
]);
this
->
highlightThreads
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"header_margin"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"header_margin"
))
{
this
->
header
->
m
argin
=
atoi
(
option
[
1
]);
this
->
header
M
argin
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"expand_system_time"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"expand_system_time"
))
{
// Compatibility option.
// Compatibility option.
this
->
pl
->
detailedCPUTime
=
atoi
(
option
[
1
]);
this
->
detailedCPUTime
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"detailed_cpu_time"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"detailed_cpu_time"
))
{
this
->
pl
->
detailedCPUTime
=
atoi
(
option
[
1
]);
this
->
detailedCPUTime
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"cpu_count_from_zero"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"cpu_count_from_zero"
))
{
this
->
pl
->
countCPUsFromZero
=
atoi
(
option
[
1
]);
this
->
countCPUsFromZero
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"update_process_names"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"update_process_names"
))
{
this
->
pl
->
updateProcessNames
=
atoi
(
option
[
1
]);
this
->
updateProcessNames
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"account_guest_in_cpu_meter"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"account_guest_in_cpu_meter"
))
{
this
->
pl
->
accountGuestInCPUMeter
=
atoi
(
option
[
1
]);
this
->
accountGuestInCPUMeter
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"delay"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"delay"
))
{
this
->
delay
=
atoi
(
option
[
1
]);
this
->
delay
=
atoi
(
option
[
1
]);
}
else
if
(
String_eq
(
option
[
0
],
"color_scheme"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"color_scheme"
))
{
...
@@ -154,96 +212,118 @@ static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
...
@@ -154,96 +212,118 @@ static bool Settings_read(Settings* this, const char* fileName, int cpuCount) {
if
(
this
->
colorScheme
<
0
)
this
->
colorScheme
=
0
;
if
(
this
->
colorScheme
<
0
)
this
->
colorScheme
=
0
;
if
(
this
->
colorScheme
>
5
)
this
->
colorScheme
=
5
;
if
(
this
->
colorScheme
>
5
)
this
->
colorScheme
=
5
;
}
else
if
(
String_eq
(
option
[
0
],
"left_meters"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"left_meters"
))
{
Settings_readMeters
(
this
,
option
[
1
],
LEFT_HEADER
);
Settings_readMeters
(
this
,
option
[
1
],
0
);
readMeters
=
true
;
readMeters
=
true
;
}
else
if
(
String_eq
(
option
[
0
],
"right_meters"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"right_meters"
))
{
Settings_readMeters
(
this
,
option
[
1
],
RIGHT_HEADER
);
Settings_readMeters
(
this
,
option
[
1
],
1
);
readMeters
=
true
;
readMeters
=
true
;
}
else
if
(
String_eq
(
option
[
0
],
"left_meter_modes"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"left_meter_modes"
))
{
Settings_readMeterModes
(
this
,
option
[
1
],
LEFT_HEADER
);
Settings_readMeterModes
(
this
,
option
[
1
],
0
);
readMeters
=
true
;
readMeters
=
true
;
}
else
if
(
String_eq
(
option
[
0
],
"right_meter_modes"
))
{
}
else
if
(
String_eq
(
option
[
0
],
"right_meter_modes"
))
{
Settings_readMeterModes
(
this
,
option
[
1
],
RIGHT_HEADER
);
Settings_readMeterModes
(
this
,
option
[
1
],
1
);
readMeters
=
true
;
readMeters
=
true
;
}
}
String_freeArray
(
option
);
String_freeArray
(
option
);
}
}
fclose
(
fd
);
fclose
(
fd
);
if
(
!
readMeters
)
{
if
(
!
readMeters
)
{
Settings_defaultMeters
(
this
->
header
,
cpuCount
);
Settings_defaultMeters
(
this
,
cpuCount
);
}
}
return
true
;
return
true
;
}
}
static
void
writeFields
(
FILE
*
fd
,
ProcessField
*
fields
,
const
char
*
name
)
{
fprintf
(
fd
,
"%s="
,
name
);
for
(
int
i
=
0
;
fields
[
i
];
i
++
)
{
// This "-1" is for compatibility with the older enum format.
fprintf
(
fd
,
"%d "
,
(
int
)
fields
[
i
]
-
1
);
}
fprintf
(
fd
,
"
\n
"
);
}
static
void
writeMeters
(
Settings
*
this
,
FILE
*
fd
,
int
column
)
{
for
(
int
i
=
0
;
i
<
this
->
columns
[
column
].
len
;
i
++
)
{
fprintf
(
fd
,
"%s "
,
this
->
columns
[
column
].
names
[
i
]);
}
fprintf
(
fd
,
"
\n
"
);
}
static
void
writeMeterModes
(
Settings
*
this
,
FILE
*
fd
,
int
column
)
{
for
(
int
i
=
0
;
i
<
this
->
columns
[
column
].
len
;
i
++
)
{
fprintf
(
fd
,
"%d "
,
this
->
columns
[
column
].
modes
[
i
]);
}
fprintf
(
fd
,
"
\n
"
);
}
bool
Settings_write
(
Settings
*
this
)
{
bool
Settings_write
(
Settings
*
this
)
{
// TODO: implement File object and make
// file I/O object-oriented.
FILE
*
fd
;
FILE
*
fd
;
fd
=
fopen
(
this
->
userSettings
,
"w"
);
fd
=
fopen
(
this
->
filename
,
"w"
);
if
(
fd
==
NULL
)
{
if
(
fd
==
NULL
)
{
return
false
;
return
false
;
}
}
fprintf
(
fd
,
"# Beware! This file is rewritten by htop when settings are changed in the interface.
\n
"
);
fprintf
(
fd
,
"# Beware! This file is rewritten by htop when settings are changed in the interface.
\n
"
);
fprintf
(
fd
,
"# The parser is also very primitive, and not human-friendly.
\n
"
);
fprintf
(
fd
,
"# The parser is also very primitive, and not human-friendly.
\n
"
);
fprintf
(
fd
,
"fields="
);
writeFields
(
fd
,
this
->
fields
,
"fields"
);
for
(
int
i
=
0
;
this
->
pl
->
fields
[
i
];
i
++
)
{
// This "-1" is for compatibility with the older enum format.
fprintf
(
fd
,
"%d "
,
(
int
)
this
->
pl
->
fields
[
i
]
-
1
);
}
fprintf
(
fd
,
"
\n
"
);
// This "-1" is for compatibility with the older enum format.
// This "-1" is for compatibility with the older enum format.
fprintf
(
fd
,
"sort_key=%d
\n
"
,
(
int
)
this
->
pl
->
sortKey
-
1
);
fprintf
(
fd
,
"sort_key=%d
\n
"
,
(
int
)
this
->
sortKey
-
1
);
fprintf
(
fd
,
"sort_direction=%d
\n
"
,
(
int
)
this
->
pl
->
direction
);
fprintf
(
fd
,
"sort_direction=%d
\n
"
,
(
int
)
this
->
direction
);
fprintf
(
fd
,
"hide_threads=%d
\n
"
,
(
int
)
this
->
pl
->
hideThreads
);
fprintf
(
fd
,
"hide_threads=%d
\n
"
,
(
int
)
this
->
hideThreads
);
fprintf
(
fd
,
"hide_kernel_threads=%d
\n
"
,
(
int
)
this
->
pl
->
hideKernelThreads
);
fprintf
(
fd
,
"hide_kernel_threads=%d
\n
"
,
(
int
)
this
->
hideKernelThreads
);
fprintf
(
fd
,
"hide_userland_threads=%d
\n
"
,
(
int
)
this
->
pl
->
hideUserlandThreads
);
fprintf
(
fd
,
"hide_userland_threads=%d
\n
"
,
(
int
)
this
->
hideUserlandThreads
);
fprintf
(
fd
,
"shadow_other_users=%d
\n
"
,
(
int
)
this
->
pl
->
shadowOtherUsers
);
fprintf
(
fd
,
"shadow_other_users=%d
\n
"
,
(
int
)
this
->
shadowOtherUsers
);
fprintf
(
fd
,
"show_thread_names=%d
\n
"
,
(
int
)
this
->
pl
->
showThreadNames
);
fprintf
(
fd
,
"show_thread_names=%d
\n
"
,
(
int
)
this
->
showThreadNames
);
fprintf
(
fd
,
"highlight_base_name=%d
\n
"
,
(
int
)
this
->
pl
->
highlightBaseName
);
fprintf
(
fd
,
"highlight_base_name=%d
\n
"
,
(
int
)
this
->
highlightBaseName
);
fprintf
(
fd
,
"highlight_megabytes=%d
\n
"
,
(
int
)
this
->
pl
->
highlightMegabytes
);
fprintf
(
fd
,
"highlight_megabytes=%d
\n
"
,
(
int
)
this
->
highlightMegabytes
);
fprintf
(
fd
,
"highlight_threads=%d
\n
"
,
(
int
)
this
->
pl
->
highlightThreads
);
fprintf
(
fd
,
"highlight_threads=%d
\n
"
,
(
int
)
this
->
highlightThreads
);
fprintf
(
fd
,
"tree_view=%d
\n
"
,
(
int
)
this
->
pl
->
treeView
);
fprintf
(
fd
,
"tree_view=%d
\n
"
,
(
int
)
this
->
treeView
);
fprintf
(
fd
,
"header_margin=%d
\n
"
,
(
int
)
this
->
header
->
m
argin
);
fprintf
(
fd
,
"header_margin=%d
\n
"
,
(
int
)
this
->
header
M
argin
);
fprintf
(
fd
,
"detailed_cpu_time=%d
\n
"
,
(
int
)
this
->
pl
->
detailedCPUTime
);
fprintf
(
fd
,
"detailed_cpu_time=%d
\n
"
,
(
int
)
this
->
detailedCPUTime
);
fprintf
(
fd
,
"cpu_count_from_zero=%d
\n
"
,
(
int
)
this
->
pl
->
countCPUsFromZero
);
fprintf
(
fd
,
"cpu_count_from_zero=%d
\n
"
,
(
int
)
this
->
countCPUsFromZero
);
fprintf
(
fd
,
"update_process_names=%d
\n
"
,
(
int
)
this
->
pl
->
updateProcessNames
);
fprintf
(
fd
,
"update_process_names=%d
\n
"
,
(
int
)
this
->
updateProcessNames
);
fprintf
(
fd
,
"account_guest_in_cpu_meter=%d
\n
"
,
(
int
)
this
->
pl
->
accountGuestInCPUMeter
);
fprintf
(
fd
,
"account_guest_in_cpu_meter=%d
\n
"
,
(
int
)
this
->
accountGuestInCPUMeter
);
fprintf
(
fd
,
"color_scheme=%d
\n
"
,
(
int
)
this
->
colorScheme
);
fprintf
(
fd
,
"color_scheme=%d
\n
"
,
(
int
)
this
->
colorScheme
);
fprintf
(
fd
,
"delay=%d
\n
"
,
(
int
)
this
->
delay
);
fprintf
(
fd
,
"delay=%d
\n
"
,
(
int
)
this
->
delay
);
fprintf
(
fd
,
"left_meters="
);
fprintf
(
fd
,
"left_meters="
);
writeMeters
(
this
,
fd
,
0
);
for
(
int
i
=
0
;
i
<
Header_size
(
this
->
header
,
LEFT_HEADER
);
i
++
)
{
fprintf
(
fd
,
"left_meter_modes="
);
writeMeterModes
(
this
,
fd
,
0
);
char
*
name
=
Header_readMeterName
(
this
->
header
,
i
,
LEFT_HEADER
);
fprintf
(
fd
,
"right_meters="
);
writeMeters
(
this
,
fd
,
1
);
fprintf
(
fd
,
"%s "
,
name
);
fprintf
(
fd
,
"right_meter_modes="
);
writeMeterModes
(
this
,
fd
,
1
);
free
(
name
);
}
fprintf
(
fd
,
"
\n
"
);
fprintf
(
fd
,
"left_meter_modes="
);
for
(
int
i
=
0
;
i
<
Header_size
(
this
->
header
,
LEFT_HEADER
);
i
++
)
fprintf
(
fd
,
"%d "
,
Header_readMeterMode
(
this
->
header
,
i
,
LEFT_HEADER
));
fprintf
(
fd
,
"
\n
"
);
fprintf
(
fd
,
"right_meters="
);
for
(
int
i
=
0
;
i
<
Header_size
(
this
->
header
,
RIGHT_HEADER
);
i
++
)
{
char
*
name
=
Header_readMeterName
(
this
->
header
,
i
,
RIGHT_HEADER
);
fprintf
(
fd
,
"%s "
,
name
);
free
(
name
);
}
fprintf
(
fd
,
"
\n
"
);
fprintf
(
fd
,
"right_meter_modes="
);
for
(
int
i
=
0
;
i
<
Header_size
(
this
->
header
,
RIGHT_HEADER
);
i
++
)
fprintf
(
fd
,
"%d "
,
Header_readMeterMode
(
this
->
header
,
i
,
RIGHT_HEADER
));
fprintf
(
fd
,
"
\n
"
);
fclose
(
fd
);
fclose
(
fd
);
return
true
;
return
true
;
}
}
Settings
*
Settings_new
(
ProcessList
*
pl
,
Header
*
header
,
int
cpuCount
)
{
Settings
*
Settings_new
(
int
cpuCount
)
{
Settings
*
this
=
malloc
(
sizeof
(
Settings
));
this
->
pl
=
pl
;
Settings
*
this
=
calloc
(
1
,
sizeof
(
Settings
));
this
->
header
=
header
;
this
->
sortKey
=
PERCENT_CPU
;
this
->
direction
=
1
;
this
->
hideThreads
=
false
;
this
->
shadowOtherUsers
=
false
;
this
->
showThreadNames
=
false
;
this
->
hideKernelThreads
=
false
;
this
->
hideUserlandThreads
=
false
;
this
->
treeView
=
false
;
this
->
highlightBaseName
=
false
;
this
->
highlightMegabytes
=
false
;
this
->
detailedCPUTime
=
false
;
this
->
countCPUsFromZero
=
false
;
this
->
updateProcessNames
=
false
;
this
->
fields
=
calloc
(
LAST_PROCESSFIELD
+
1
,
sizeof
(
ProcessField
));
// TODO: turn 'fields' into a Vector,
// (and ProcessFields into proper objects).
this
->
flags
=
0
;
ProcessField
*
defaults
=
defaultFields
;
for
(
int
i
=
0
;
defaults
[
i
];
i
++
)
{
this
->
fields
[
i
]
=
defaults
[
i
];
this
->
flags
|=
Process_fields
[
defaults
[
i
]].
flags
;
}
char
*
legacyDotfile
=
NULL
;
char
*
legacyDotfile
=
NULL
;
char
*
rcfile
=
getenv
(
"HTOPRC"
);
char
*
rcfile
=
getenv
(
"HTOPRC"
);
if
(
rcfile
)
{
if
(
rcfile
)
{
this
->
userSettings
=
strdup
(
rcfile
);
this
->
filename
=
strdup
(
rcfile
);
}
else
{
}
else
{
const
char
*
home
=
getenv
(
"HOME"
);
const
char
*
home
=
getenv
(
"HOME"
);
if
(
!
home
)
home
=
""
;
if
(
!
home
)
home
=
""
;
...
@@ -251,11 +331,11 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
...
@@ -251,11 +331,11 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
char
*
configDir
=
NULL
;
char
*
configDir
=
NULL
;
char
*
htopDir
=
NULL
;
char
*
htopDir
=
NULL
;
if
(
xdgConfigHome
)
{
if
(
xdgConfigHome
)
{
this
->
userSettings
=
String_cat
(
xdgConfigHome
,
"/htop/htoprc"
);
this
->
filename
=
String_cat
(
xdgConfigHome
,
"/htop/htoprc"
);
configDir
=
strdup
(
xdgConfigHome
);
configDir
=
strdup
(
xdgConfigHome
);
htopDir
=
String_cat
(
xdgConfigHome
,
"/htop"
);
htopDir
=
String_cat
(
xdgConfigHome
,
"/htop"
);
}
else
{
}
else
{
this
->
userSettings
=
String_cat
(
home
,
"/.config/htop/htoprc"
);
this
->
filename
=
String_cat
(
home
,
"/.config/htop/htoprc"
);
configDir
=
String_cat
(
home
,
"/.config"
);
configDir
=
String_cat
(
home
,
"/.config"
);
htopDir
=
String_cat
(
home
,
"/.config/htop"
);
htopDir
=
String_cat
(
home
,
"/.config/htop"
);
}
}
...
@@ -276,7 +356,7 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
...
@@ -276,7 +356,7 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
this
->
colorScheme
=
0
;
this
->
colorScheme
=
0
;
this
->
changed
=
false
;
this
->
changed
=
false
;
this
->
delay
=
DEFAULT_DELAY
;
this
->
delay
=
DEFAULT_DELAY
;
bool
ok
=
Settings_read
(
this
,
legacyDotfile
?
legacyDotfile
:
this
->
userSettings
,
cpuCount
);
bool
ok
=
Settings_read
(
this
,
legacyDotfile
?
legacyDotfile
:
this
->
filename
,
cpuCount
);
if
(
ok
)
{
if
(
ok
)
{
if
(
legacyDotfile
)
{
if
(
legacyDotfile
)
{
// Transition to new location and delete old configuration file
// Transition to new location and delete old configuration file
...
@@ -290,12 +370,19 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
...
@@ -290,12 +370,19 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
ok
=
Settings_read
(
this
,
systemSettings
,
cpuCount
);
ok
=
Settings_read
(
this
,
systemSettings
,
cpuCount
);
free
(
systemSettings
);
free
(
systemSettings
);
if
(
!
ok
)
{
if
(
!
ok
)
{
Settings_defaultMeters
(
this
->
header
,
cpuCount
);
Settings_defaultMeters
(
this
,
cpuCount
);
pl
->
hideKernelThreads
=
true
;
this
->
hideKernelThreads
=
true
;
pl
->
highlightMegabytes
=
true
;
this
->
highlightMegabytes
=
true
;
pl
->
highlightThreads
=
false
;
this
->
highlightThreads
=
false
;
}
}
}
}
free
(
legacyDotfile
);
free
(
legacyDotfile
);
return
this
;
return
this
;
}
}
void
Settings_invertSortOrder
(
Settings
*
this
)
{
if
(
this
->
direction
==
1
)
this
->
direction
=
-
1
;
else
this
->
direction
=
1
;
}
Settings.h
View file @
d2acffa5
...
@@ -11,24 +11,57 @@ in the source distribution for its full text.
...
@@ -11,24 +11,57 @@ in the source distribution for its full text.
#define DEFAULT_DELAY 15
#define DEFAULT_DELAY 15
#include "ProcessList.h"
#include "Process.h"
#include "Header.h"
#include <stdbool.h>
#include <stdbool.h>
typedef
struct
{
int
len
;
char
**
names
;
int
*
modes
;
}
MeterColumnSettings
;
typedef
struct
Settings_
{
typedef
struct
Settings_
{
char
*
userSettings
;
char
*
filename
;
ProcessList
*
pl
;
Header
*
header
;
MeterColumnSettings
columns
[
2
];
ProcessField
*
fields
;
int
flags
;
int
colorScheme
;
int
colorScheme
;
int
delay
;
int
delay
;
int
direction
;
ProcessField
sortKey
;
bool
countCPUsFromZero
;
bool
detailedCPUTime
;
bool
treeView
;
bool
hideThreads
;
bool
shadowOtherUsers
;
bool
showThreadNames
;
bool
hideKernelThreads
;
bool
hideUserlandThreads
;
bool
highlightBaseName
;
bool
highlightMegabytes
;
bool
highlightThreads
;
bool
updateProcessNames
;
bool
accountGuestInCPUMeter
;
bool
headerMargin
;
bool
changed
;
bool
changed
;
}
Settings
;
}
Settings
;
#ifndef Settings_cpuId
#define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromZero ? (cpu) : (cpu)+1)
#endif
void
Settings_delete
(
Settings
*
this
);
void
Settings_delete
(
Settings
*
this
);
bool
Settings_write
(
Settings
*
this
);
bool
Settings_write
(
Settings
*
this
);
Settings
*
Settings_new
(
ProcessList
*
pl
,
Header
*
header
,
int
cpuCount
);
Settings
*
Settings_new
(
int
cpuCount
);
void
Settings_invertSortOrder
(
Settings
*
this
);
#endif
#endif
SwapMeter.c
View file @
d2acffa5
...
@@ -8,7 +8,7 @@ in the source distribution for its full text.
...
@@ -8,7 +8,7 @@ in the source distribution for its full text.
#include "SwapMeter.h"
#include "SwapMeter.h"
#include "CRT.h"
#include "CRT.h"
#include "P
rocessList
.h"
#include "P
latform
.h"
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
...
@@ -34,11 +34,8 @@ static void SwapMeter_humanNumber(char* buffer, const long int* value) {
...
@@ -34,11 +34,8 @@ static void SwapMeter_humanNumber(char* buffer, const long int* value) {
}
}
static
void
SwapMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
static
void
SwapMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
long
int
usedSwap
=
this
->
pl
->
usedSwap
;
Platform_setSwapValues
(
this
);
this
->
total
=
this
->
pl
->
totalSwap
;
snprintf
(
buffer
,
len
,
"%ld/%ldMB"
,
(
long
int
)
this
->
values
[
0
]
/
MEGABYTE
,
(
long
int
)
this
->
total
/
MEGABYTE
);
this
->
values
[
0
]
=
usedSwap
;
snprintf
(
buffer
,
len
,
"%ld/%ldMB"
,
(
long
int
)
usedSwap
/
MEGABYTE
,
(
long
int
)
this
->
total
/
MEGABYTE
);
}
}
static
void
SwapMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
static
void
SwapMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
...
...
TasksMeter.c
View file @
d2acffa5
...
@@ -7,7 +7,7 @@ in the source distribution for its full text.
...
@@ -7,7 +7,7 @@ in the source distribution for its full text.
#include "TasksMeter.h"
#include "TasksMeter.h"
#include "P
rocessList
.h"
#include "P
latform
.h"
#include "CRT.h"
#include "CRT.h"
/*{
/*{
...
@@ -15,42 +15,46 @@ in the source distribution for its full text.
...
@@ -15,42 +15,46 @@ in the source distribution for its full text.
}*/
}*/
int
TasksMeter_attributes
[]
=
{
int
TasksMeter_attributes
[]
=
{
TASKS_RUNNING
CPU_KERNEL
,
PROCESS_THREAD
,
PROCESS
,
TASKS_RUNNING
};
};
static
void
TasksMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
static
void
TasksMeter_setValues
(
Meter
*
this
,
char
*
buffer
,
int
len
)
{
ProcessList
*
pl
=
this
->
pl
;
Platform_setTasksValues
(
this
);
this
->
total
=
pl
->
totalTasks
;
if
(
this
->
pl
->
settings
->
hideKernelThreads
)
{
this
->
values
[
0
]
=
pl
->
runningTasks
;
this
->
values
[
0
]
=
0
;
snprintf
(
buffer
,
len
,
"%d/%d"
,
(
int
)
this
->
values
[
0
],
(
int
)
this
->
total
);
}
snprintf
(
buffer
,
len
,
"%d/%d"
,
(
int
)
this
->
values
[
3
],
(
int
)
this
->
total
);
}
}
static
void
TasksMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
static
void
TasksMeter_display
(
Object
*
cast
,
RichString
*
out
)
{
Meter
*
this
=
(
Meter
*
)
cast
;
Meter
*
this
=
(
Meter
*
)
cast
;
ProcessList
*
pl
=
this
->
pl
;
Settings
*
settings
=
this
->
pl
->
settings
;
char
buffer
[
20
];
char
buffer
[
20
];
sprintf
(
buffer
,
"%d"
,
(
int
)(
this
->
total
-
pl
->
userlandThreads
-
pl
->
kernelThreads
));
int
processes
=
(
int
)
this
->
values
[
2
];
sprintf
(
buffer
,
"%d"
,
processes
);
RichString_write
(
out
,
CRT_colors
[
METER_VALUE
],
buffer
);
RichString_write
(
out
,
CRT_colors
[
METER_VALUE
],
buffer
);
int
threadValueColor
=
CRT_colors
[
METER_VALUE
];
int
threadValueColor
=
CRT_colors
[
METER_VALUE
];
int
threadCaptionColor
=
CRT_colors
[
METER_TEXT
];
int
threadCaptionColor
=
CRT_colors
[
METER_TEXT
];
if
(
pl
->
highlightThreads
)
{
if
(
settings
->
highlightThreads
)
{
threadValueColor
=
CRT_colors
[
PROCESS_THREAD_BASENAME
];
threadValueColor
=
CRT_colors
[
PROCESS_THREAD_BASENAME
];
threadCaptionColor
=
CRT_colors
[
PROCESS_THREAD
];
threadCaptionColor
=
CRT_colors
[
PROCESS_THREAD
];
}
}
if
(
!
pl
->
hideUserlandThreads
)
{
if
(
!
settings
->
hideUserlandThreads
)
{
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
", "
);
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
", "
);
sprintf
(
buffer
,
"%d"
,
(
int
)
pl
->
userlandThreads
);
sprintf
(
buffer
,
"%d"
,
(
int
)
this
->
values
[
1
]
);
RichString_append
(
out
,
threadValueColor
,
buffer
);
RichString_append
(
out
,
threadValueColor
,
buffer
);
RichString_append
(
out
,
threadCaptionColor
,
" thr"
);
RichString_append
(
out
,
threadCaptionColor
,
" thr"
);
}
}
if
(
!
pl
->
hideKernelThreads
)
{
if
(
!
settings
->
hideKernelThreads
)
{
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
", "
);
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
", "
);
sprintf
(
buffer
,
"%d"
,
(
int
)
pl
->
kernelThreads
);
sprintf
(
buffer
,
"%d"
,
(
int
)
this
->
values
[
0
]
);
RichString_append
(
out
,
threadValueColor
,
buffer
);
RichString_append
(
out
,
threadValueColor
,
buffer
);
RichString_append
(
out
,
threadCaptionColor
,
" kthr"
);
RichString_append
(
out
,
threadCaptionColor
,
" kthr"
);
}
}
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
"; "
);
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
"; "
);
sprintf
(
buffer
,
"%d"
,
(
int
)
this
->
values
[
0
]);
sprintf
(
buffer
,
"%d"
,
(
int
)
this
->
values
[
3
]);
RichString_append
(
out
,
CRT_colors
[
TASKS_RUNNING
],
buffer
);
RichString_append
(
out
,
CRT_colors
[
TASKS_RUNNING
],
buffer
);
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
" running"
);
RichString_append
(
out
,
CRT_colors
[
METER_TEXT
],
" running"
);
}
}
...
@@ -64,6 +68,7 @@ MeterClass TasksMeter_class = {
...
@@ -64,6 +68,7 @@ MeterClass TasksMeter_class = {
.
setValues
=
TasksMeter_setValues
,
.
setValues
=
TasksMeter_setValues
,
.
defaultMode
=
TEXT_METERMODE
,
.
defaultMode
=
TEXT_METERMODE
,
.
total
=
100
.
0
,
.
total
=
100
.
0
,
.
maxItems
=
4
,
.
attributes
=
TasksMeter_attributes
,
.
attributes
=
TasksMeter_attributes
,
.
name
=
"Tasks"
,
.
name
=
"Tasks"
,
.
uiName
=
"Task counter"
,
.
uiName
=
"Task counter"
,
...
...
Vector.c
View file @
d2acffa5
...
@@ -192,6 +192,10 @@ void Vector_insert(Vector* this, int idx, void* data_) {
...
@@ -192,6 +192,10 @@ void Vector_insert(Vector* this, int idx, void* data_) {
assert
(
idx
<=
this
->
items
);
assert
(
idx
<=
this
->
items
);
assert
(
Object_isA
(
data
,
this
->
type
));
assert
(
Object_isA
(
data
,
this
->
type
));
assert
(
Vector_isConsistent
(
this
));
assert
(
Vector_isConsistent
(
this
));
if
(
idx
>
this
->
items
)
{
idx
=
this
->
items
;
}
Vector_checkArraySize
(
this
);
Vector_checkArraySize
(
this
);
//assert(this->array[this->items] == NULL);
//assert(this->array[this->items] == NULL);
...
...
configure.ac
View file @
d2acffa5
...
@@ -4,6 +4,8 @@
...
@@ -4,6 +4,8 @@
AC_PREREQ(2.65)
AC_PREREQ(2.65)
AC_INIT([htop],[1.0.3],[hisham@gobolinux.org])
AC_INIT([htop],[1.0.3],[hisham@gobolinux.org])
year=$(date +%Y)
# The following two lines are required by hwloc scripts
# The following two lines are required by hwloc scripts
AC_USE_SYSTEM_EXTENSIONS
AC_USE_SYSTEM_EXTENSIONS
AC_CANONICAL_TARGET
AC_CANONICAL_TARGET
...
@@ -71,6 +73,19 @@ AC_TRY_COMPILE(AC_INCLUDES_DEFAULT, [char *a; a = strdup("foo"); int i = 0; i++;
...
@@ -71,6 +73,19 @@ AC_TRY_COMPILE(AC_INCLUDES_DEFAULT, [char *a; a = strdup("foo"); int i = 0; i++;
AC_MSG_ERROR([htop is written in C99. A newer version of gcc is required.]))
AC_MSG_ERROR([htop is written in C99. A newer version of gcc is required.]))
CFLAGS="$save_cflags"
CFLAGS="$save_cflags"
save_cflags="${CFLAGS}"
CFLAGS="$CFLAGS -Wextra"
AC_MSG_CHECKING([if compiler supports -Wextra])
AC_TRY_COMPILE([], [], [
wextra_flag=-Wextra
AC_MSG_RESULT([yes])
],[
wextra_flag=
AC_MSG_RESULT([no])
])
CFLAGS="$save_cflags"
AC_SUBST(wextra_flag)
# Checks for features and flags.
# Checks for features and flags.
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
PROCDIR=/proc
PROCDIR=/proc
...
@@ -187,6 +202,8 @@ if test ! -z "$missing_headers"; then
...
@@ -187,6 +202,8 @@ if test ! -z "$missing_headers"; then
AC_MSG_ERROR([missing headers: $missing_headers])
AC_MSG_ERROR([missing headers: $missing_headers])
fi
fi
AC_DEFINE_UNQUOTED(COPYRIGHT, "(C) 2004-$year Hisham Muhammad", [Copyright message.])
# We're done, let's go!
# We're done, let's go!
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
AM_CONDITIONAL([HTOP_LINUX], [test "$my_htop_platform" = linux])
AM_CONDITIONAL([HTOP_LINUX], [test "$my_htop_platform" = linux])
...
...
htop.1.in
View file @
d2acffa5
...
@@ -319,13 +319,13 @@ Bytes of write(2) I/O for the process.
...
@@ -319,13 +319,13 @@ Bytes of write(2) I/O for the process.
.B CNCLWB (IO_CANCEL)
.B CNCLWB (IO_CANCEL)
Bytes of cancelled write(2) I/O.
Bytes of cancelled write(2) I/O.
.TP
.TP
.B IO_READ_RATE (
IORR
)
.B IO_READ_RATE (
DISK READ
)
The I/O rate of read(2) in bytes per second, for the process.
The I/O rate of read(2) in bytes per second, for the process.
.TP
.TP
.B IO_WRITE_RATE (
IOWR
)
.B IO_WRITE_RATE (
DISK WRITE
)
The I/O rate of write(2) in bytes per second, for the process.
The I/O rate of write(2) in bytes per second, for the process.
.TP
.TP
.B IO_RATE (
IOR
W)
.B IO_RATE (
DISK R/
W)
The I/O rate, IO_READ_RATE + IO_WRITE_RATE (see above).
The I/O rate, IO_READ_RATE + IO_WRITE_RATE (see above).
.TP
.TP
.B CGROUP
.B CGROUP
...
...
htop.c
View file @
d2acffa5
...
@@ -5,45 +5,28 @@ Released under the GNU GPL, see the COPYING file
...
@@ -5,45 +5,28 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
in the source distribution for its full text.
*/
*/
#include "
ProcessList
.h"
#include "
config
.h"
#include "CRT.h"
#include "Panel.h"
#include "UsersTable.h"
#include "RichString.h"
#include "Settings.h"
#include "ScreenManager.h"
#include "FunctionBar.h"
#include "FunctionBar.h"
#include "ListItem.h"
#include "Hashtable.h"
#include "String.h"
#include "ColumnsPanel.h"
#include "ColumnsPanel.h"
#include "CategoriesPanel.h"
#include "CRT.h"
#include "SignalsPanel.h"
#include "MainPanel.h"
#include "TraceScreen.h"
#include "ProcessList.h"
#include "OpenFilesScreen.h"
#include "ScreenManager.h"
#include "AffinityPanel.h"
#include "Settings.h"
#include "Platform.h"
#include "UsersTable.h"
#include "IncSet.h"
#include "Action.h"
#include "htop.h"
#include <unistd.h>
#include <math.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <locale.h>
#include <getopt.h>
#include <getopt.h>
#include <pwd.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
#include <time.h>
#include <unistd.h>
//#link m
//#link m
#define COPYRIGHT "(C) 2004-2014 Hisham Muhammad"
static
void
printVersionFlag
()
{
static
void
printVersionFlag
()
{
fputs
(
"htop "
VERSION
" - "
COPYRIGHT
"
\n
"
fputs
(
"htop "
VERSION
" - "
COPYRIGHT
"
\n
"
"Released under the GNU GPL.
\n\n
"
,
"Released under the GNU GPL.
\n\n
"
,
...
@@ -71,505 +54,26 @@ static void printHelpFlag() {
...
@@ -71,505 +54,26 @@ static void printHelpFlag() {
exit
(
0
);
exit
(
0
);
}
}
static
struct
{
const
char
*
key
;
const
char
*
info
;
}
helpLeft
[]
=
{
{
.
key
=
" Arrows: "
,
.
info
=
"scroll process list"
},
{
.
key
=
" Digits: "
,
.
info
=
"incremental PID search"
},
{
.
key
=
" F3 /: "
,
.
info
=
"incremental name search"
},
{
.
key
=
" F4
\\
: "
,.
info
=
"incremental name filtering"
},
{
.
key
=
" F5 t: "
,
.
info
=
"tree view"
},
{
.
key
=
" u: "
,
.
info
=
"show processes of a single user"
},
{
.
key
=
" H: "
,
.
info
=
"hide/show user threads"
},
{
.
key
=
" K: "
,
.
info
=
"hide/show kernel threads"
},
{
.
key
=
" F: "
,
.
info
=
"cursor follows process"
},
{
.
key
=
" F6 + -: "
,
.
info
=
"expand/collapse tree"
},
{
.
key
=
" P M T: "
,
.
info
=
"sort by CPU%, MEM% or TIME"
},
{
.
key
=
" I: "
,
.
info
=
"invert sort order"
},
{
.
key
=
" F6 >: "
,
.
info
=
"select sort column"
},
{
.
key
=
NULL
,
.
info
=
NULL
}
};
static
struct
{
const
char
*
key
;
const
char
*
info
;
}
helpRight
[]
=
{
{
.
key
=
" Space: "
,
.
info
=
"tag process"
},
{
.
key
=
" c: "
,
.
info
=
"tag process and its children"
},
{
.
key
=
" U: "
,
.
info
=
"untag all processes"
},
{
.
key
=
" F9 k: "
,
.
info
=
"kill process/tagged processes"
},
{
.
key
=
" F7 ]: "
,
.
info
=
"higher priority (root only)"
},
{
.
key
=
" F8 [: "
,
.
info
=
"lower priority (+ nice)"
},
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
{
.
key
=
" a: "
,
.
info
=
"set CPU affinity"
},
#endif
{
.
key
=
" i: "
,
.
info
=
"set IO prority"
},
{
.
key
=
" l: "
,
.
info
=
"list open files with lsof"
},
{
.
key
=
" s: "
,
.
info
=
"trace syscalls with strace"
},
{
.
key
=
" "
,
.
info
=
""
},
{
.
key
=
" F2 S: "
,
.
info
=
"setup"
},
{
.
key
=
" F1 h: "
,
.
info
=
"show this help screen"
},
{
.
key
=
" F10 q: "
,
.
info
=
"quit"
},
{
.
key
=
NULL
,
.
info
=
NULL
}
};
static
void
showHelp
(
ProcessList
*
pl
)
{
clear
();
attrset
(
CRT_colors
[
HELP_BOLD
]);
for
(
int
i
=
0
;
i
<
LINES
-
1
;
i
++
)
mvhline
(
i
,
0
,
' '
,
COLS
);
mvaddstr
(
0
,
0
,
"htop "
VERSION
" - "
COPYRIGHT
);
mvaddstr
(
1
,
0
,
"Released under the GNU GPL. See 'man' page for more info."
);
attrset
(
CRT_colors
[
DEFAULT_COLOR
]);
mvaddstr
(
3
,
0
,
"CPU usage bar: "
);
#define addattrstr(a,s) attrset(a);addstr(s)
addattrstr
(
CRT_colors
[
BAR_BORDER
],
"["
);
if
(
pl
->
detailedCPUTime
)
{
addattrstr
(
CRT_colors
[
CPU_NICE_TEXT
],
"low"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_NORMAL
],
"normal"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_KERNEL
],
"kernel"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_IRQ
],
"irq"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_SOFTIRQ
],
"soft-irq"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_STEAL
],
"steal"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_GUEST
],
"guest"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_IOWAIT
],
"io-wait"
);
addattrstr
(
CRT_colors
[
BAR_SHADOW
],
" used%"
);
}
else
{
addattrstr
(
CRT_colors
[
CPU_NICE_TEXT
],
"low-priority"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_NORMAL
],
"normal"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_KERNEL
],
"kernel"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
CPU_STEAL
],
"virtualiz"
);
addattrstr
(
CRT_colors
[
BAR_SHADOW
],
" used%"
);
}
addattrstr
(
CRT_colors
[
BAR_BORDER
],
"]"
);
attrset
(
CRT_colors
[
DEFAULT_COLOR
]);
mvaddstr
(
4
,
0
,
"Memory bar: "
);
addattrstr
(
CRT_colors
[
BAR_BORDER
],
"["
);
addattrstr
(
CRT_colors
[
MEMORY_USED
],
"used"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
MEMORY_BUFFERS_TEXT
],
"buffers"
);
addstr
(
"/"
);
addattrstr
(
CRT_colors
[
MEMORY_CACHE
],
"cache"
);
addattrstr
(
CRT_colors
[
BAR_SHADOW
],
" used/total"
);
addattrstr
(
CRT_colors
[
BAR_BORDER
],
"]"
);
attrset
(
CRT_colors
[
DEFAULT_COLOR
]);
mvaddstr
(
5
,
0
,
"Swap bar: "
);
addattrstr
(
CRT_colors
[
BAR_BORDER
],
"["
);
addattrstr
(
CRT_colors
[
SWAP
],
"used"
);
addattrstr
(
CRT_colors
[
BAR_SHADOW
],
" used/total"
);
addattrstr
(
CRT_colors
[
BAR_BORDER
],
"]"
);
attrset
(
CRT_colors
[
DEFAULT_COLOR
]);
mvaddstr
(
6
,
0
,
"Type and layout of header meters are configurable in the setup screen."
);
if
(
CRT_colorScheme
==
COLORSCHEME_MONOCHROME
)
{
mvaddstr
(
7
,
0
,
"In monochrome, meters are displayed through different chars, in order: |#*@$%&"
);
}
mvaddstr
(
8
,
0
,
" Status: R: running; S: sleeping; T: traced/stopped; Z: zombie; D: disk sleep"
);
for
(
int
i
=
0
;
helpLeft
[
i
].
info
;
i
++
)
{
mvaddstr
(
9
+
i
,
9
,
helpLeft
[
i
].
info
);
}
for
(
int
i
=
0
;
helpRight
[
i
].
info
;
i
++
)
{
mvaddstr
(
9
+
i
,
49
,
helpRight
[
i
].
info
);
}
attrset
(
CRT_colors
[
HELP_BOLD
]);
for
(
int
i
=
0
;
helpLeft
[
i
].
key
;
i
++
)
{
mvaddstr
(
9
+
i
,
0
,
helpLeft
[
i
].
key
);
}
for
(
int
i
=
0
;
helpRight
[
i
].
key
;
i
++
)
{
mvaddstr
(
9
+
i
,
40
,
helpRight
[
i
].
key
);
}
attrset
(
CRT_colors
[
HELP_BOLD
]);
mvaddstr
(
23
,
0
,
"Press any key to return."
);
attrset
(
CRT_colors
[
DEFAULT_COLOR
]);
refresh
();
CRT_readKey
();
clear
();
}
static
const
char
*
CategoriesFunctions
[]
=
{
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"Done "
,
NULL
};
static
void
Setup_run
(
Settings
*
settings
,
const
Header
*
header
)
{
ScreenManager
*
scr
=
ScreenManager_new
(
0
,
header
->
height
,
0
,
-
1
,
HORIZONTAL
,
header
,
true
);
CategoriesPanel
*
panelCategories
=
CategoriesPanel_new
(
settings
,
scr
);
ScreenManager_add
(
scr
,
(
Panel
*
)
panelCategories
,
FunctionBar_new
(
CategoriesFunctions
,
NULL
,
NULL
),
16
);
CategoriesPanel_makeMetersPage
(
panelCategories
);
Panel
*
panelFocus
;
int
ch
;
ScreenManager_run
(
scr
,
&
panelFocus
,
&
ch
);
ScreenManager_delete
(
scr
);
}
static
bool
changePriority
(
Panel
*
panel
,
int
delta
)
{
bool
anyTagged
;
bool
ok
=
Action_foreachProcess
(
panel
,
(
Action_ForeachProcessFn
)
Process_changePriorityBy
,
delta
,
&
anyTagged
);
if
(
!
ok
)
beep
();
return
anyTagged
;
}
static
void
addUserToVector
(
int
key
,
void
*
userCast
,
void
*
panelCast
)
{
char
*
user
=
(
char
*
)
userCast
;
Panel
*
panel
=
(
Panel
*
)
panelCast
;
Panel_add
(
panel
,
(
Object
*
)
ListItem_new
(
user
,
key
));
}
static
bool
setUserOnly
(
const
char
*
userName
,
bool
*
userOnly
,
uid_t
*
userId
)
{
struct
passwd
*
user
=
getpwnam
(
userName
);
if
(
user
)
{
*
userOnly
=
true
;
*
userId
=
user
->
pw_uid
;
return
true
;
}
return
false
;
}
static
const
char
*
getMainPanelValue
(
Panel
*
panel
,
int
i
)
{
Process
*
p
=
(
Process
*
)
Panel_get
(
panel
,
i
);
if
(
p
)
return
p
->
comm
;
return
""
;
}
static
void
tagAllChildren
(
Panel
*
panel
,
Process
*
parent
)
{
parent
->
tag
=
true
;
pid_t
ppid
=
parent
->
pid
;
for
(
int
i
=
0
;
i
<
Panel_size
(
panel
);
i
++
)
{
Process
*
p
=
(
Process
*
)
Panel_get
(
panel
,
i
);
if
(
!
p
->
tag
&&
p
->
ppid
==
ppid
)
{
tagAllChildren
(
panel
,
p
);
}
}
}
static
bool
expandCollapse
(
Panel
*
panel
)
{
Process
*
p
=
(
Process
*
)
Panel_getSelected
(
panel
);
if
(
!
p
)
return
false
;
p
->
showChildren
=
!
p
->
showChildren
;
return
true
;
}
static
inline
Htop_Reaction
setSortKey
(
ProcessList
*
pl
,
ProcessField
sortKey
)
{
pl
->
sortKey
=
sortKey
;
pl
->
direction
=
1
;
pl
->
treeView
=
false
;
return
HTOP_REFRESH
|
HTOP_SAVE_SETTINGS
|
HTOP_UPDATE_PANELHDR
;
}
static
Htop_Reaction
sortBy
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
)
{
Htop_Reaction
reaction
=
HTOP_OK
;
Panel
*
sortPanel
=
Panel_new
(
0
,
0
,
0
,
0
,
true
,
Class
(
ListItem
));
Panel_setHeader
(
sortPanel
,
"Sort by"
);
const
char
*
fuFunctions
[]
=
{
"Sort "
,
"Cancel "
,
NULL
};
ProcessField
*
fields
=
pl
->
fields
;
for
(
int
i
=
0
;
fields
[
i
];
i
++
)
{
char
*
name
=
String_trim
(
Process_fieldNames
[
fields
[
i
]]);
Panel_add
(
sortPanel
,
(
Object
*
)
ListItem_new
(
name
,
fields
[
i
]));
if
(
fields
[
i
]
==
pl
->
sortKey
)
Panel_setSelected
(
sortPanel
,
i
);
free
(
name
);
}
ListItem
*
field
=
(
ListItem
*
)
Action_pickFromVector
(
panel
,
sortPanel
,
15
,
fuFunctions
,
header
);
if
(
field
)
{
reaction
|=
setSortKey
(
pl
,
field
->
key
);
}
Object_delete
(
sortPanel
);
return
reaction
|
HTOP_REFRESH
|
HTOP_REDRAW_BAR
|
HTOP_UPDATE_PANELHDR
;
}
static
void
millisleep
(
unsigned
long
millisec
)
{
struct
timespec
req
=
{
.
tv_sec
=
0
,
.
tv_nsec
=
millisec
*
1000000L
};
while
(
nanosleep
(
&
req
,
&
req
)
==-
1
)
{
continue
;
}
}
// ----------------------------------------
// ----------------------------------------
static
Htop_Reaction
actionResize
(
Panel
*
panel
)
{
typedef
struct
CommandLineSettings_
{
Panel_resize
(
panel
,
COLS
,
LINES
-
(
panel
->
y
)
-
1
);
Hashtable
*
pidWhiteList
;
return
HTOP_REDRAW_BAR
;
uid_t
userId
;
}
int
sortKey
;
int
delay
;
static
Htop_Reaction
actionSortByMemory
(
Panel
*
panel
,
ProcessList
*
pl
)
{
bool
useColors
;
(
void
)
panel
;
}
CommandLineSettings
;
return
setSortKey
(
pl
,
PERCENT_MEM
);
}
static
CommandLineSettings
parseArguments
(
int
argc
,
char
**
argv
)
{
static
Htop_Reaction
actionSortByCPU
(
Panel
*
panel
,
ProcessList
*
pl
)
{
CommandLineSettings
flags
=
{
(
void
)
panel
;
.
pidWhiteList
=
NULL
,
return
setSortKey
(
pl
,
PERCENT_CPU
);
.
userId
=
-
1
,
// -1 is guaranteed to be an invalid uid_t (see setreuid(2))
}
.
sortKey
=
0
,
.
delay
=
-
1
,
static
Htop_Reaction
actionSortByTime
(
Panel
*
panel
,
ProcessList
*
pl
)
{
.
useColors
=
true
,
(
void
)
panel
;
};
return
setSortKey
(
pl
,
TIME
);
}
static
Htop_Reaction
actionToggleKernelThreads
(
Panel
*
panel
,
ProcessList
*
pl
)
{
(
void
)
panel
;
pl
->
hideKernelThreads
=
!
pl
->
hideKernelThreads
;
return
HTOP_RECALCULATE
|
HTOP_SAVE_SETTINGS
;
}
static
Htop_Reaction
actionToggleUserlandThreads
(
Panel
*
panel
,
ProcessList
*
pl
)
{
(
void
)
panel
;
pl
->
hideUserlandThreads
=
!
pl
->
hideUserlandThreads
;
pl
->
hideThreads
=
pl
->
hideUserlandThreads
;
return
HTOP_RECALCULATE
|
HTOP_SAVE_SETTINGS
;
}
static
Htop_Reaction
actionToggleTreeView
(
Panel
*
panel
,
ProcessList
*
pl
)
{
(
void
)
panel
;
pl
->
treeView
=
!
pl
->
treeView
;
if
(
pl
->
treeView
)
pl
->
direction
=
1
;
ProcessList_expandTree
(
pl
);
return
HTOP_REFRESH
|
HTOP_SAVE_SETTINGS
|
HTOP_KEEP_FOLLOWING
|
HTOP_REDRAW_BAR
|
HTOP_UPDATE_PANELHDR
;
}
static
Htop_Reaction
actionIncFilter
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
,
State
*
state
)
{
(
void
)
panel
,
(
void
)
pl
,
(
void
)
header
;
IncSet_activate
(
state
->
inc
,
INC_FILTER
);
return
HTOP_REFRESH
|
HTOP_KEEP_FOLLOWING
;
}
static
Htop_Reaction
actionIncSearch
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
,
State
*
state
)
{
(
void
)
panel
,
(
void
)
pl
,
(
void
)
header
;
IncSet_activate
(
state
->
inc
,
INC_SEARCH
);
return
HTOP_REFRESH
|
HTOP_KEEP_FOLLOWING
;
}
static
Htop_Reaction
actionHigherPriority
(
Panel
*
panel
)
{
bool
changed
=
changePriority
(
panel
,
-
1
);
return
changed
?
HTOP_REFRESH
:
HTOP_OK
;
}
static
Htop_Reaction
actionLowerPriority
(
Panel
*
panel
)
{
bool
changed
=
changePriority
(
panel
,
1
);
return
changed
?
HTOP_REFRESH
:
HTOP_OK
;
}
static
Htop_Reaction
actionInvertSortOrder
(
Panel
*
panel
,
ProcessList
*
pl
)
{
(
void
)
panel
;
ProcessList_invertSortOrder
(
pl
);
return
HTOP_REFRESH
|
HTOP_SAVE_SETTINGS
;
}
static
Htop_Reaction
actionSetSortColumn
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
)
{
return
sortBy
(
panel
,
pl
,
header
);
}
static
Htop_Reaction
actionExpandOrCollapse
(
Panel
*
panel
)
{
bool
changed
=
expandCollapse
(
panel
);
return
changed
?
HTOP_RECALCULATE
:
HTOP_OK
;
}
static
Htop_Reaction
actionExpandCollapseOrSortColumn
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
)
{
return
pl
->
treeView
?
actionExpandOrCollapse
(
panel
)
:
actionSetSortColumn
(
panel
,
pl
,
header
);
}
static
Htop_Reaction
actionQuit
()
{
return
HTOP_QUIT
;
}
static
Htop_Reaction
actionSetAffinity
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
)
{
if
(
pl
->
cpuCount
==
1
)
return
HTOP_OK
;
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
Process
*
p
=
(
Process
*
)
Panel_getSelected
(
panel
);
if
(
!
p
)
return
HTOP_OK
;
Affinity
*
affinity
=
Process_getAffinity
(
p
);
if
(
!
affinity
)
return
HTOP_OK
;
Panel
*
affinityPanel
=
AffinityPanel_new
(
pl
,
affinity
);
Affinity_delete
(
affinity
);
const
char
*
fuFunctions
[]
=
{
"Set "
,
"Cancel "
,
NULL
};
void
*
set
=
Action_pickFromVector
(
panel
,
affinityPanel
,
15
,
fuFunctions
,
header
);
if
(
set
)
{
Affinity
*
affinity
=
AffinityPanel_getAffinity
(
affinityPanel
);
bool
ok
=
Action_foreachProcess
(
panel
,
(
Action_ForeachProcessFn
)
Process_setAffinity
,
(
size_t
)
affinity
,
NULL
);
if
(
!
ok
)
beep
();
Affinity_delete
(
affinity
);
}
Panel_delete
((
Object
*
)
affinityPanel
);
#else
(
void
)
panel
;
(
void
)
header
;
#endif
return
HTOP_REFRESH
|
HTOP_REDRAW_BAR
|
HTOP_UPDATE_PANELHDR
;
}
static
Htop_Reaction
actionKill
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
)
{
(
void
)
pl
;
Panel
*
signalsPanel
=
(
Panel
*
)
SignalsPanel_new
();
const
char
*
fuFunctions
[]
=
{
"Send "
,
"Cancel "
,
NULL
};
ListItem
*
sgn
=
(
ListItem
*
)
Action_pickFromVector
(
panel
,
signalsPanel
,
15
,
fuFunctions
,
header
);
if
(
sgn
)
{
if
(
sgn
->
key
!=
0
)
{
Panel_setHeader
(
panel
,
"Sending..."
);
Panel_draw
(
panel
,
true
);
refresh
();
Action_foreachProcess
(
panel
,
(
Action_ForeachProcessFn
)
Process_sendSignal
,
(
size_t
)
sgn
->
key
,
NULL
);
napms
(
500
);
}
}
Panel_delete
((
Object
*
)
signalsPanel
);
return
HTOP_REFRESH
|
HTOP_REDRAW_BAR
|
HTOP_UPDATE_PANELHDR
;
}
static
Htop_Reaction
actionFilterByUser
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
,
State
*
state
)
{
Panel
*
usersPanel
=
Panel_new
(
0
,
0
,
0
,
0
,
true
,
Class
(
ListItem
));
Panel_setHeader
(
usersPanel
,
"Show processes of:"
);
UsersTable_foreach
(
state
->
ut
,
addUserToVector
,
usersPanel
);
Vector_insertionSort
(
usersPanel
->
items
);
ListItem
*
allUsers
=
ListItem_new
(
"All users"
,
-
1
);
Panel_insert
(
usersPanel
,
0
,
(
Object
*
)
allUsers
);
const
char
*
fuFunctions
[]
=
{
"Show "
,
"Cancel "
,
NULL
};
ListItem
*
picked
=
(
ListItem
*
)
Action_pickFromVector
(
panel
,
usersPanel
,
20
,
fuFunctions
,
header
);
if
(
picked
)
{
if
(
picked
==
allUsers
)
{
pl
->
userOnly
=
false
;
}
else
{
setUserOnly
(
ListItem_getRef
(
picked
),
&
(
pl
->
userOnly
),
&
(
pl
->
userId
));
}
}
Panel_delete
((
Object
*
)
usersPanel
);
return
HTOP_REFRESH
|
HTOP_REDRAW_BAR
|
HTOP_UPDATE_PANELHDR
;
}
static
Htop_Reaction
actionFollow
()
{
return
HTOP_KEEP_FOLLOWING
;
}
static
Htop_Reaction
actionSetup
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
,
State
*
state
)
{
(
void
)
pl
;
Setup_run
(
state
->
settings
,
header
);
// TODO: shouldn't need this, colors should be dynamic
int
headerHeight
=
Header_calculateHeight
(
header
);
Panel_move
(
panel
,
0
,
headerHeight
);
Panel_resize
(
panel
,
COLS
,
LINES
-
headerHeight
-
1
);
return
HTOP_REFRESH
|
HTOP_REDRAW_BAR
|
HTOP_UPDATE_PANELHDR
;
}
static
Htop_Reaction
actionLsof
(
Panel
*
panel
)
{
Process
*
p
=
(
Process
*
)
Panel_getSelected
(
panel
);
if
(
!
p
)
return
HTOP_OK
;
OpenFilesScreen
*
ts
=
OpenFilesScreen_new
(
p
);
OpenFilesScreen_run
(
ts
);
OpenFilesScreen_delete
(
ts
);
clear
();
CRT_enableDelay
();
return
HTOP_REFRESH
|
HTOP_REDRAW_BAR
;
}
static
Htop_Reaction
actionStrace
(
Panel
*
panel
)
{
Process
*
p
=
(
Process
*
)
Panel_getSelected
(
panel
);
if
(
!
p
)
return
HTOP_OK
;
TraceScreen
*
ts
=
TraceScreen_new
(
p
);
TraceScreen_run
(
ts
);
TraceScreen_delete
(
ts
);
clear
();
CRT_enableDelay
();
return
HTOP_REFRESH
|
HTOP_REDRAW_BAR
;
}
static
Htop_Reaction
actionTag
(
Panel
*
panel
)
{
Process
*
p
=
(
Process
*
)
Panel_getSelected
(
panel
);
if
(
!
p
)
return
HTOP_OK
;
Process_toggleTag
(
p
);
Panel_onKey
(
panel
,
KEY_DOWN
);
return
HTOP_OK
;
}
static
Htop_Reaction
actionRedraw
()
{
clear
();
return
HTOP_REFRESH
|
HTOP_REDRAW_BAR
;
}
static
Htop_Reaction
actionHelp
(
Panel
*
panel
,
ProcessList
*
pl
)
{
(
void
)
panel
;
showHelp
(
pl
);
return
HTOP_RECALCULATE
|
HTOP_REDRAW_BAR
;
}
static
Htop_Reaction
actionUntagAll
(
Panel
*
panel
)
{
for
(
int
i
=
0
;
i
<
Panel_size
(
panel
);
i
++
)
{
Process
*
p
=
(
Process
*
)
Panel_get
(
panel
,
i
);
p
->
tag
=
false
;
}
return
HTOP_REFRESH
;
}
static
Htop_Reaction
actionTagAllChildren
(
Panel
*
panel
)
{
Process
*
p
=
(
Process
*
)
Panel_getSelected
(
panel
);
if
(
!
p
)
return
HTOP_OK
;
tagAllChildren
(
panel
,
p
);
return
HTOP_OK
;
}
static
void
setBindings
(
Htop_Action
*
keys
)
{
keys
[
KEY_RESIZE
]
=
actionResize
;
keys
[
'M'
]
=
actionSortByMemory
;
keys
[
'T'
]
=
actionSortByTime
;
keys
[
'P'
]
=
actionSortByCPU
;
keys
[
'H'
]
=
actionToggleUserlandThreads
;
keys
[
'K'
]
=
actionToggleKernelThreads
;
keys
[
't'
]
=
actionToggleTreeView
;
keys
[
KEY_F
(
5
)]
=
actionToggleTreeView
;
keys
[
KEY_F
(
4
)]
=
actionIncFilter
;
keys
[
'\\'
]
=
actionIncFilter
;
keys
[
KEY_F
(
3
)]
=
actionIncSearch
;
keys
[
'/'
]
=
actionIncSearch
;
keys
[
']'
]
=
actionHigherPriority
;
keys
[
KEY_F
(
7
)]
=
actionHigherPriority
;
keys
[
'['
]
=
actionLowerPriority
;
keys
[
KEY_F
(
8
)]
=
actionLowerPriority
;
keys
[
'I'
]
=
actionInvertSortOrder
;
keys
[
KEY_F
(
6
)]
=
actionExpandCollapseOrSortColumn
;
keys
[
KEY_F
(
18
)]
=
actionExpandCollapseOrSortColumn
;
keys
[
'<'
]
=
actionSetSortColumn
;
keys
[
','
]
=
actionSetSortColumn
;
keys
[
'>'
]
=
actionSetSortColumn
;
keys
[
'.'
]
=
actionSetSortColumn
;
keys
[
KEY_F
(
10
)]
=
actionQuit
;
keys
[
'q'
]
=
actionQuit
;
keys
[
'a'
]
=
actionSetAffinity
;
keys
[
KEY_F
(
9
)]
=
actionKill
;
keys
[
'k'
]
=
actionKill
;
keys
[
'+'
]
=
actionExpandOrCollapse
;
keys
[
'='
]
=
actionExpandOrCollapse
;
keys
[
'-'
]
=
actionExpandOrCollapse
;
keys
[
'u'
]
=
actionFilterByUser
;
keys
[
'F'
]
=
actionFollow
;
keys
[
'S'
]
=
actionSetup
;
keys
[
'C'
]
=
actionSetup
;
keys
[
KEY_F
(
2
)]
=
actionSetup
;
keys
[
'l'
]
=
actionLsof
;
keys
[
's'
]
=
actionStrace
;
keys
[
' '
]
=
actionTag
;
keys
[
'\014'
]
=
actionRedraw
;
// Ctrl+L
keys
[
KEY_F
(
1
)]
=
actionHelp
;
keys
[
'h'
]
=
actionHelp
;
keys
[
'?'
]
=
actionHelp
;
keys
[
'U'
]
=
actionUntagAll
;
keys
[
'c'
]
=
actionTagAllChildren
;
}
// ----------------------------------------
static
void
updateTreeFunctions
(
FunctionBar
*
fuBar
,
bool
mode
)
{
if
(
mode
)
{
FunctionBar_setLabel
(
fuBar
,
KEY_F
(
5
),
"Sorted"
);
FunctionBar_setLabel
(
fuBar
,
KEY_F
(
6
),
"Collap"
);
}
else
{
FunctionBar_setLabel
(
fuBar
,
KEY_F
(
5
),
"Tree "
);
FunctionBar_setLabel
(
fuBar
,
KEY_F
(
6
),
"SortBy"
);
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
delay
=
-
1
;
bool
userOnly
=
false
;
uid_t
userId
=
0
;
int
usecolors
=
1
;
char
*
argCopy
;
char
*
pid
;
Hashtable
*
pidWhiteList
=
NULL
;
int
opt
,
opti
=
0
;
static
struct
option
long_opts
[]
=
static
struct
option
long_opts
[]
=
{
{
{
"help"
,
no_argument
,
0
,
'h'
},
{
"help"
,
no_argument
,
0
,
'h'
},
...
@@ -580,20 +84,13 @@ int main(int argc, char** argv) {
...
@@ -580,20 +84,13 @@ int main(int argc, char** argv) {
{
"no-color"
,
no_argument
,
0
,
'C'
},
{
"no-color"
,
no_argument
,
0
,
'C'
},
{
"no-colour"
,
no_argument
,
0
,
'C'
},
{
"no-colour"
,
no_argument
,
0
,
'C'
},
{
"pid"
,
required_argument
,
0
,
'p'
},
{
"pid"
,
required_argument
,
0
,
'p'
},
{
"io"
,
no_argument
,
0
,
'i'
},
{
0
,
0
,
0
,
0
}
{
0
,
0
,
0
,
0
}
};
};
int
sortKey
=
0
;
char
*
lc_ctype
=
getenv
(
"LC_CTYPE"
);
if
(
lc_ctype
!=
NULL
)
setlocale
(
LC_CTYPE
,
lc_ctype
);
else
if
((
lc_ctype
=
getenv
(
"LC_ALL"
)))
setlocale
(
LC_CTYPE
,
lc_ctype
);
else
setlocale
(
LC_CTYPE
,
""
);
int
opt
,
opti
=
0
;
/* Parse arguments */
/* Parse arguments */
while
((
opt
=
getopt_long
(
argc
,
argv
,
"hvCs:d:u:p:"
,
long_opts
,
&
opti
)))
{
while
((
opt
=
getopt_long
(
argc
,
argv
,
"hvCs:d:u:p:
i
"
,
long_opts
,
&
opti
)))
{
if
(
opt
==
EOF
)
break
;
if
(
opt
==
EOF
)
break
;
switch
(
opt
)
{
switch
(
opt
)
{
case
'h'
:
case
'h'
:
...
@@ -604,47 +101,48 @@ int main(int argc, char** argv) {
...
@@ -604,47 +101,48 @@ int main(int argc, char** argv) {
break
;
break
;
case
's'
:
case
's'
:
if
(
strcmp
(
optarg
,
"help"
)
==
0
)
{
if
(
strcmp
(
optarg
,
"help"
)
==
0
)
{
for
(
int
j
=
1
;
j
<
LAST_PROCESSFIELD
;
j
++
)
for
(
int
j
=
1
;
j
<
LAST_PROCESSFIELD
;
j
++
)
{
printf
(
"%s
\n
"
,
Process_fieldNames
[
j
]);
const
char
*
name
=
Process_fields
[
j
].
name
;
if
(
name
)
printf
(
"%s
\n
"
,
name
);
}
exit
(
0
);
exit
(
0
);
}
}
flags
.
sortKey
=
ColumnsPanel_fieldNameToIndex
(
optarg
);
sortKey
=
ColumnsPanel_fieldNameToIndex
(
optarg
);
if
(
flags
.
sortKey
==
-
1
)
{
if
(
sortKey
==
-
1
)
{
fprintf
(
stderr
,
"Error: invalid column
\"
%s
\"
.
\n
"
,
optarg
);
fprintf
(
stderr
,
"Error: invalid column
\"
%s
\"
.
\n
"
,
optarg
);
exit
(
1
);
exit
(
1
);
}
}
break
;
break
;
case
'd'
:
case
'd'
:
if
(
sscanf
(
optarg
,
"%16d"
,
&
delay
)
==
1
)
{
if
(
sscanf
(
optarg
,
"%16d"
,
&
(
flags
.
delay
)
)
==
1
)
{
if
(
delay
<
1
)
delay
=
1
;
if
(
flags
.
delay
<
1
)
flags
.
delay
=
1
;
if
(
delay
>
100
)
delay
=
100
;
if
(
flags
.
delay
>
100
)
flags
.
delay
=
100
;
}
else
{
}
else
{
fprintf
(
stderr
,
"Error: invalid delay value
\"
%s
\"
.
\n
"
,
optarg
);
fprintf
(
stderr
,
"Error: invalid delay value
\"
%s
\"
.
\n
"
,
optarg
);
exit
(
1
);
exit
(
1
);
}
}
break
;
break
;
case
'u'
:
case
'u'
:
if
(
!
setUserOnly
(
optarg
,
&
userOnly
,
&
userId
))
{
if
(
!
Action_
setUserOnly
(
optarg
,
&
(
flags
.
userId
))
)
{
fprintf
(
stderr
,
"Error: invalid user
\"
%s
\"
.
\n
"
,
optarg
);
fprintf
(
stderr
,
"Error: invalid user
\"
%s
\"
.
\n
"
,
optarg
);
exit
(
1
);
exit
(
1
);
}
}
break
;
break
;
case
'C'
:
case
'C'
:
use
c
olors
=
0
;
flags
.
use
C
olors
=
false
;
break
;
break
;
case
'p'
:
{
case
'p'
:
{
argCopy
=
strdup
(
optarg
);
char
*
argCopy
=
strdup
(
optarg
);
char
*
saveptr
;
char
*
saveptr
;
pid
=
strtok_r
(
argCopy
,
","
,
&
saveptr
);
char
*
pid
=
strtok_r
(
argCopy
,
","
,
&
saveptr
);
if
(
!
pidWhiteList
)
{
if
(
!
flags
.
pidWhiteList
)
{
pidWhiteList
=
Hashtable_new
(
8
,
false
);
flags
.
pidWhiteList
=
Hashtable_new
(
8
,
false
);
}
}
while
(
pid
)
{
while
(
pid
)
{
unsigned
int
num_pid
=
atoi
(
pid
);
unsigned
int
num_pid
=
atoi
(
pid
);
Hashtable_put
(
pidWhiteList
,
num_pid
,
(
void
*
)
1
);
Hashtable_put
(
flags
.
pidWhiteList
,
num_pid
,
(
void
*
)
1
);
pid
=
strtok_r
(
NULL
,
","
,
&
saveptr
);
pid
=
strtok_r
(
NULL
,
","
,
&
saveptr
);
}
}
free
(
argCopy
);
free
(
argCopy
);
...
@@ -655,6 +153,30 @@ int main(int argc, char** argv) {
...
@@ -655,6 +153,30 @@ int main(int argc, char** argv) {
exit
(
1
);
exit
(
1
);
}
}
}
}
return
flags
;
}
static
void
millisleep
(
unsigned
long
millisec
)
{
struct
timespec
req
=
{
.
tv_sec
=
0
,
.
tv_nsec
=
millisec
*
1000000L
};
while
(
nanosleep
(
&
req
,
&
req
)
==-
1
)
{
continue
;
}
}
int
main
(
int
argc
,
char
**
argv
)
{
char
*
lc_ctype
=
getenv
(
"LC_CTYPE"
);
if
(
lc_ctype
!=
NULL
)
setlocale
(
LC_CTYPE
,
lc_ctype
);
else
if
((
lc_ctype
=
getenv
(
"LC_ALL"
)))
setlocale
(
LC_CTYPE
,
lc_ctype
);
else
setlocale
(
LC_CTYPE
,
""
);
CommandLineSettings
flags
=
parseArguments
(
argc
,
argv
);
// may exit()
#ifdef HAVE_PROC
#ifdef HAVE_PROC
if
(
access
(
PROCDIR
,
R_OK
)
!=
0
)
{
if
(
access
(
PROCDIR
,
R_OK
)
!=
0
)
{
...
@@ -677,43 +199,61 @@ int main(int argc, char** argv) {
...
@@ -677,43 +199,61 @@ int main(int argc, char** argv) {
CRT_utf8
=
false
;
CRT_utf8
=
false
;
#endif
#endif
UsersTable
*
ut
=
UsersTable_new
();
ProcessList
*
pl
=
ProcessList_new
(
ut
,
pidWhiteList
);
pl
->
userOnly
=
userOnly
;
pl
->
userId
=
userId
;
Process_setupColumnWidths
();
Process_setupColumnWidths
();
Header
*
header
=
Header_new
(
pl
);
UsersTable
*
ut
=
UsersTable_new
();
Settings
*
settings
=
Settings_new
(
pl
,
header
,
pl
->
cpuCount
);
ProcessList
*
pl
=
ProcessList_new
(
ut
,
flags
.
pidWhiteList
,
flags
.
userId
);
int
headerHeight
=
Header_calculateHeight
(
header
);
Settings
*
settings
=
Settings_new
(
pl
->
cpuCount
);
// FIXME: move delay code to settings
pl
->
settings
=
settings
;
if
(
delay
!=
-
1
)
settings
->
delay
=
delay
;
Header
*
header
=
Header_new
(
pl
,
settings
,
2
);
if
(
!
usecolors
)
Header_populateFromSettings
(
header
);
if
(
flags
.
delay
!=
-
1
)
settings
->
delay
=
flags
.
delay
;
if
(
!
flags
.
useColors
)
settings
->
colorScheme
=
COLORSCHEME_MONOCHROME
;
settings
->
colorScheme
=
COLORSCHEME_MONOCHROME
;
CRT_init
(
settings
->
delay
,
settings
->
colorScheme
);
CRT_init
(
settings
->
delay
,
settings
->
colorScheme
);
Panel
*
panel
=
Panel_new
(
0
,
headerHeight
,
COLS
,
LINES
-
headerHeight
-
2
,
false
,
&
Process_class
);
ProcessList_setPanel
(
pl
,
panel
);
FunctionBar
*
defaultBar
=
FunctionBar_new
(
defaultFunctions
,
NULL
,
NULL
);
FunctionBar
*
defaultBar
=
FunctionBar_new
(
defaultFunctions
,
NULL
,
NULL
);
updateTreeFunctions
(
defaultBar
,
pl
->
treeView
);
if
(
sortKey
>
0
)
{
MainPanel
*
panel
=
MainPanel_new
(
defaultBar
);
pl
->
sortKey
=
sortKey
;
ProcessList_setPanel
(
pl
,
(
Panel
*
)
panel
);
pl
->
treeView
=
false
;
pl
->
direction
=
1
;
MainPanel_updateTreeFunctions
(
defaultBar
,
settings
->
treeView
);
if
(
flags
.
sortKey
>
0
)
{
settings
->
sortKey
=
flags
.
sortKey
;
settings
->
treeView
=
false
;
settings
->
direction
=
1
;
}
}
ProcessList_printHeader
(
pl
,
Panel_getHeader
(
panel
));
ProcessList_printHeader
(
pl
,
Panel_getHeader
(
(
Panel
*
)
panel
));
IncSet
*
inc
=
IncSet_new
(
defaultBar
);
IncSet
*
inc
=
IncSet_new
(
defaultBar
);
State
state
=
{
.
inc
=
inc
,
.
settings
=
settings
,
.
ut
=
ut
,
.
pl
=
pl
,
.
panel
=
(
Panel
*
)
panel
,
.
header
=
header
,
};
MainPanel_setState
(
panel
,
&
state
);
ScreenManager
*
scr
=
ScreenManager_new
(
0
,
header
->
height
,
0
,
-
1
,
HORIZONTAL
,
header
,
settings
,
true
);
ScreenManager_add
(
scr
,
(
Panel
*
)
panel
,
defaultBar
,
-
1
);
ProcessList_scan
(
pl
);
ProcessList_scan
(
pl
);
millisleep
(
75
);
millisleep
(
75
);
ProcessList_scan
(
pl
);
ProcessList_scan
(
pl
);
ScreenManager_run
(
scr
,
NULL
,
NULL
);
/*
FunctionBar_draw(defaultBar, NULL);
FunctionBar_draw(defaultBar, NULL);
int acc = 0;
int acc = 0;
...
@@ -732,12 +272,6 @@ int main(int argc, char** argv) {
...
@@ -732,12 +272,6 @@ int main(int argc, char** argv) {
Htop_Action keys[KEY_MAX] = { NULL };
Htop_Action keys[KEY_MAX] = { NULL };
setBindings(keys);
setBindings(keys);
Platform_setBindings(keys);
Platform_setBindings(keys);
State
state
=
{
.
inc
=
inc
,
.
settings
=
settings
,
.
ut
=
ut
,
};
bool quit = false;
bool quit = false;
int sortTimeout = 0;
int sortTimeout = 0;
...
@@ -750,7 +284,7 @@ int main(int argc, char** argv) {
...
@@ -750,7 +284,7 @@ int main(int argc, char** argv) {
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
bool timeToRecalculate = (newTime - oldTime > settings->delay);
bool timeToRecalculate = (newTime - oldTime > settings->delay);
if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
int
following
=
follow
?
Action
_selectedPid
(
panel
)
:
-
1
;
int following = follow ?
MainPanel
_selectedPid(
(MainPanel*)
panel) : -1;
if (timeToRecalculate) {
if (timeToRecalculate) {
Header_draw(header);
Header_draw(header);
oldTime = newTime;
oldTime = newTime;
...
@@ -760,7 +294,7 @@ int main(int argc, char** argv) {
...
@@ -760,7 +294,7 @@ int main(int argc, char** argv) {
ProcessList_scan(pl);
ProcessList_scan(pl);
forceRecalculate = false;
forceRecalculate = false;
}
}
if
(
sortTimeout
==
0
||
pl
->
treeView
)
{
if (sortTimeout == 0 ||
settings
->treeView) {
ProcessList_sort(pl);
ProcessList_sort(pl);
sortTimeout = 1;
sortTimeout = 1;
}
}
...
@@ -769,7 +303,7 @@ int main(int argc, char** argv) {
...
@@ -769,7 +303,7 @@ int main(int argc, char** argv) {
}
}
doRefresh = true;
doRefresh = true;
if
(
pl
->
treeView
)
{
if (
settings
->treeView) {
Process* p = (Process*) Panel_getSelected(panel);
Process* p = (Process*) Panel_getSelected(panel);
if (p) {
if (p) {
if (!p->showChildren && !collapsed) {
if (!p->showChildren && !collapsed) {
...
@@ -819,12 +353,12 @@ int main(int argc, char** argv) {
...
@@ -819,12 +353,12 @@ int main(int argc, char** argv) {
if (mevent.y == panel->y) {
if (mevent.y == panel->y) {
int x = panel->scrollH + mevent.x + 1;
int x = panel->scrollH + mevent.x + 1;
ProcessField field = ProcessList_keyAt(pl, x);
ProcessField field = ProcessList_keyAt(pl, x);
if
(
field
==
pl
->
sortKey
)
{
if (field ==
settings
->sortKey) {
ProcessList
_invertSortOrder
(
pl
);
Settings
_invertSortOrder(
settings
);
pl
->
treeView
=
false
;
settings
->treeView = false;
reaction |= HTOP_REDRAW_BAR;
reaction |= HTOP_REDRAW_BAR;
} else {
} else {
reaction
|=
setSortKey
(
pl
,
field
);
reaction |= setSortKey(
settings
, field);
}
}
sortTimeout = 0;
sortTimeout = 0;
ch = ERR;
ch = ERR;
...
@@ -872,7 +406,7 @@ int main(int argc, char** argv) {
...
@@ -872,7 +406,7 @@ int main(int argc, char** argv) {
}
}
if(ch != ERR && keys[ch]) {
if(ch != ERR && keys[ch]) {
reaction
|=
(
keys
[
ch
])(
panel
,
pl
,
header
,
&
state
);
reaction |= (keys[ch])(&state);
} else {
} else {
doRefresh = false;
doRefresh = false;
sortTimeout = resetSortTimeout;
sortTimeout = resetSortTimeout;
...
@@ -882,7 +416,7 @@ int main(int argc, char** argv) {
...
@@ -882,7 +416,7 @@ int main(int argc, char** argv) {
// Reaction handlers:
// Reaction handlers:
if (reaction & HTOP_REDRAW_BAR) {
if (reaction & HTOP_REDRAW_BAR) {
updateTreeFunctions
(
defaultBar
,
pl
->
treeView
);
updateTreeFunctions(defaultBar,
settings
->treeView);
IncSet_drawBar(inc);
IncSet_drawBar(inc);
}
}
if (reaction & HTOP_UPDATE_PANELHDR) {
if (reaction & HTOP_UPDATE_PANELHDR) {
...
@@ -904,6 +438,9 @@ int main(int argc, char** argv) {
...
@@ -904,6 +438,9 @@ int main(int argc, char** argv) {
}
}
follow = (reaction & HTOP_KEEP_FOLLOWING);
follow = (reaction & HTOP_KEEP_FOLLOWING);
}
}
*/
attron
(
CRT_colors
[
RESET_COLOR
]);
attron
(
CRT_colors
[
RESET_COLOR
]);
mvhline
(
LINES
-
1
,
0
,
' '
,
COLS
);
mvhline
(
LINES
-
1
,
0
,
' '
,
COLS
);
attroff
(
CRT_colors
[
RESET_COLOR
]);
attroff
(
CRT_colors
[
RESET_COLOR
]);
...
@@ -914,16 +451,20 @@ int main(int argc, char** argv) {
...
@@ -914,16 +451,20 @@ int main(int argc, char** argv) {
Settings_write
(
settings
);
Settings_write
(
settings
);
Header_delete
(
header
);
Header_delete
(
header
);
ProcessList_delete
(
pl
);
ProcessList_delete
(
pl
);
/*
FunctionBar_delete((Object*)defaultBar);
FunctionBar_delete((Object*)defaultBar);
Panel_delete((Object*)panel);
Panel_delete((Object*)panel);
*/
ScreenManager_delete
(
scr
);
IncSet_delete
(
inc
);
IncSet_delete
(
inc
);
UsersTable_delete
(
ut
);
UsersTable_delete
(
ut
);
Settings_delete
(
settings
);
Settings_delete
(
settings
);
if
(
pidWhiteList
)
{
if
(
flags
.
pidWhiteList
)
{
Hashtable_delete
(
pidWhiteList
);
Hashtable_delete
(
flags
.
pidWhiteList
);
}
}
return
0
;
return
0
;
}
}
htop.h
View file @
d2acffa5
...
@@ -11,11 +11,8 @@ in the source distribution for its full text.
...
@@ -11,11 +11,8 @@ in the source distribution for its full text.
//#link m
//#link m
#define COPYRIGHT "(C) 2004-2014 Hisham Muhammad"
// ----------------------------------------
// ----------------------------------------
// ----------------------------------------
int
main
(
int
argc
,
char
**
argv
);
int
main
(
int
argc
,
char
**
argv
);
...
...
linux/Battery.c
View file @
d2acffa5
...
@@ -11,28 +11,24 @@ Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat
...
@@ -11,28 +11,24 @@ Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat
#define _GNU_SOURCE
#define _GNU_SOURCE
#endif
#endif
#include <dirent.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include "BatteryMeter.h"
#include "BatteryMeter.h"
#include "String.h"
#include "String.h"
static
unsigned
long
int
parseUevent
(
FILE
*
file
,
const
char
*
key
)
{
#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply"
char
line
[
100
];
unsigned
long
int
dValue
=
0
;
// ----------------------------------------
char
*
saveptr
;
// READ FROM /proc
// ----------------------------------------
while
(
fgets
(
line
,
sizeof
line
,
file
))
{
if
(
strncmp
(
line
,
key
,
strlen
(
key
))
==
0
)
{
// This implementation reading from from /proc/acpi is really inefficient,
char
*
value
;
// but I think this is on the way out so I did not rewrite it.
strtok_r
(
line
,
"="
,
&
saveptr
);
// The /sys implementation below does things the right way.
value
=
strtok_r
(
NULL
,
"="
,
&
saveptr
);
dValue
=
atoi
(
value
);
break
;
}
}
return
dValue
;
}
static
unsigned
long
int
parseBatInfo
(
const
char
*
fileName
,
const
unsigned
short
int
lineNum
,
const
unsigned
short
int
wordNum
)
{
static
unsigned
long
int
parseBatInfo
(
const
char
*
fileName
,
const
unsigned
short
int
lineNum
,
const
unsigned
short
int
wordNum
)
{
const
char
batteryPath
[]
=
PROCDIR
"/acpi/battery/"
;
const
char
batteryPath
[]
=
PROCDIR
"/acpi/battery/"
;
...
@@ -94,15 +90,15 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short
...
@@ -94,15 +90,15 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short
static
ACPresence
procAcpiCheck
()
{
static
ACPresence
procAcpiCheck
()
{
ACPresence
isOn
=
AC_ERROR
;
ACPresence
isOn
=
AC_ERROR
;
const
char
*
power_supplyPath
=
PROCDIR
"/acpi/ac_adapter"
;
const
char
*
power_supplyPath
=
PROCDIR
"/acpi/ac_adapter"
;
DIR
*
power_supplyD
ir
=
opendir
(
power_supplyPath
);
DIR
*
d
ir
=
opendir
(
power_supplyPath
);
if
(
!
power_supplyD
ir
)
{
if
(
!
d
ir
)
{
return
AC_ERROR
;
return
AC_ERROR
;
}
}
struct
dirent
result
;
struct
dirent
result
;
struct
dirent
*
dirEntry
;
struct
dirent
*
dirEntry
;
for
(;;)
{
for
(;;)
{
int
err
=
readdir_r
((
DIR
*
)
power_supplyD
ir
,
&
result
,
&
dirEntry
);
int
err
=
readdir_r
((
DIR
*
)
d
ir
,
&
result
,
&
dirEntry
);
if
(
err
||
!
dirEntry
)
if
(
err
||
!
dirEntry
)
break
;
break
;
...
@@ -121,7 +117,8 @@ static ACPresence procAcpiCheck() {
...
@@ -121,7 +117,8 @@ static ACPresence procAcpiCheck() {
}
}
char
line
[
100
];
char
line
[
100
];
fgets
(
line
,
sizeof
line
,
file
);
char
*
ok
=
fgets
(
line
,
sizeof
line
,
file
);
if
(
!
ok
)
continue
;
line
[
sizeof
(
line
)
-
1
]
=
'\0'
;
line
[
sizeof
(
line
)
-
1
]
=
'\0'
;
fclose
(
file
);
fclose
(
file
);
...
@@ -139,62 +136,12 @@ static ACPresence procAcpiCheck() {
...
@@ -139,62 +136,12 @@ static ACPresence procAcpiCheck() {
}
}
}
}
if
(
power_supplyDir
)
if
(
dir
)
closedir
(
power_supplyDir
);
closedir
(
dir
);
return
isOn
;
}
static
ACPresence
sysCheck
()
{
ACPresence
isOn
=
AC_ERROR
;
const
char
*
power_supplyPath
=
"/sys/class/power_supply"
;
DIR
*
power_supplyDir
=
opendir
(
power_supplyPath
);
if
(
!
power_supplyDir
)
{
return
AC_ERROR
;
}
struct
dirent
result
;
struct
dirent
*
dirEntry
;
for
(;;)
{
int
err
=
readdir_r
((
DIR
*
)
power_supplyDir
,
&
result
,
&
dirEntry
);
if
(
err
||
!
dirEntry
)
break
;
char
*
entryName
=
(
char
*
)
dirEntry
->
d_name
;
if
(
strncmp
(
entryName
,
"A"
,
1
))
{
continue
;
}
char
onlinePath
[
50
];
snprintf
((
char
*
)
onlinePath
,
sizeof
onlinePath
,
"%s/%s/online"
,
power_supplyPath
,
entryName
);
FILE
*
file
=
fopen
(
onlinePath
,
"r"
);
if
(
!
file
)
{
isOn
=
AC_ERROR
;
}
else
{
isOn
=
(
fgetc
(
file
)
-
'0'
);
fclose
(
file
);
if
(
isOn
==
AC_PRESENT
)
{
// If any AC adapter is being used then stop
break
;
}
}
}
if
(
power_supplyDir
)
closedir
(
power_supplyDir
);
return
isOn
;
return
isOn
;
}
}
ACPresence
Battery_isOnAC
()
{
static
double
Battery_getProcBatData
()
{
if
(
access
(
PROCDIR
"/acpi/ac_adapter"
,
F_OK
)
==
0
)
{
return
procAcpiCheck
();
}
else
if
(
access
(
"/sys/class/power_supply"
,
F_OK
)
==
0
)
{
return
sysCheck
();
}
else
{
return
AC_ERROR
;
}
}
double
Battery_getProcBatData
()
{
const
unsigned
long
int
totalFull
=
parseBatInfo
(
"info"
,
3
,
4
);
const
unsigned
long
int
totalFull
=
parseBatInfo
(
"info"
,
3
,
4
);
if
(
totalFull
==
0
)
if
(
totalFull
==
0
)
return
0
;
return
0
;
...
@@ -206,11 +153,58 @@ double Battery_getProcBatData() {
...
@@ -206,11 +153,58 @@ double Battery_getProcBatData() {
return
totalRemain
*
100
.
0
/
(
double
)
totalFull
;
return
totalRemain
*
100
.
0
/
(
double
)
totalFull
;
}
}
double
Battery_getSysBatData
()
{
static
void
Battery_getProcData
(
double
*
level
,
ACPresence
*
isOnAC
)
{
const
char
*
power_supplyPath
=
"/sys/class/power_supply/"
;
*
level
=
Battery_getProcBatData
();
DIR
*
power_supplyDir
=
opendir
(
power_supplyPath
);
*
isOnAC
=
procAcpiCheck
();
if
(
!
power_supplyDir
)
}
return
0
;
// ----------------------------------------
// READ FROM /sys
// ----------------------------------------
static
inline
ssize_t
xread
(
int
fd
,
void
*
buf
,
size_t
count
)
{
// Read some bytes. Retry on EINTR and when we don't get as many bytes as we requested.
size_t
alreadyRead
=
0
;
for
(;;)
{
ssize_t
res
=
read
(
fd
,
buf
,
count
);
if
(
res
==
-
1
&&
errno
==
EINTR
)
continue
;
if
(
res
>
0
)
{
buf
=
((
char
*
)
buf
)
+
res
;
count
-=
res
;
alreadyRead
+=
res
;
}
if
(
res
==
-
1
)
return
-
1
;
if
(
count
==
0
||
res
==
0
)
return
alreadyRead
;
}
}
/**
* Returns a pointer to the suffix of `str` if its beginning matches `prefix`.
* Returns NULL if the prefix does not match.
* Examples:
* match("hello world", "hello "); -> "world"
* match("hello world", "goodbye "); -> NULL
*/
static
inline
const
char
*
match
(
const
char
*
str
,
const
char
*
prefix
)
{
for
(;;)
{
if
(
*
prefix
==
'\0'
)
{
return
str
;
}
if
(
*
prefix
!=
*
str
)
{
return
NULL
;
}
prefix
++
;
str
++
;
}
}
static
void
Battery_getSysData
(
double
*
level
,
ACPresence
*
isOnAC
)
{
*
level
=
0
;
*
isOnAC
=
AC_ERROR
;
DIR
*
dir
=
opendir
(
SYS_POWERSUPPLY_DIR
);
if
(
!
dir
)
return
;
unsigned
long
int
totalFull
=
0
;
unsigned
long
int
totalFull
=
0
;
unsigned
long
int
totalRemain
=
0
;
unsigned
long
int
totalRemain
=
0
;
...
@@ -218,52 +212,120 @@ double Battery_getSysBatData() {
...
@@ -218,52 +212,120 @@ double Battery_getSysBatData() {
struct
dirent
result
;
struct
dirent
result
;
struct
dirent
*
dirEntry
;
struct
dirent
*
dirEntry
;
for
(;;)
{
for
(;;)
{
int
err
=
readdir_r
((
DIR
*
)
power_supplyD
ir
,
&
result
,
&
dirEntry
);
int
err
=
readdir_r
((
DIR
*
)
d
ir
,
&
result
,
&
dirEntry
);
if
(
err
||
!
dirEntry
)
if
(
err
||
!
dirEntry
)
break
;
break
;
char
*
entryName
=
(
char
*
)
dirEntry
->
d_name
;
char
*
entryName
=
(
char
*
)
dirEntry
->
d_name
;
const
char
filePath
[
50
];
if
(
strncmp
(
entryName
,
"BAT"
,
3
))
{
continue
;
if
(
entryName
[
0
]
==
'B'
&&
entryName
[
1
]
==
'A'
&&
entryName
[
2
]
==
'T'
)
{
snprintf
((
char
*
)
filePath
,
sizeof
filePath
,
SYS_POWERSUPPLY_DIR
"/%s/uevent"
,
entryName
);
int
fd
=
open
(
filePath
,
O_RDONLY
);
if
(
fd
==
-
1
)
{
closedir
(
dir
);
return
;
}
char
buffer
[
1024
];
ssize_t
buflen
=
xread
(
fd
,
buffer
,
1023
);
close
(
fd
);
if
(
buflen
<
1
)
{
closedir
(
dir
);
return
;
}
buffer
[
buflen
]
=
'\0'
;
char
*
buf
=
buffer
;
char
*
line
=
NULL
;
bool
full
=
false
;
bool
now
=
false
;
while
((
line
=
strsep
(
&
buf
,
"
\n
"
))
!=
NULL
)
{
const
char
*
ps
=
match
(
line
,
"POWER_SUPPLY_"
);
if
(
!
ps
)
{
continue
;
}
const
char
*
energy
=
match
(
ps
,
"ENERGY_"
);
if
(
!
energy
)
{
energy
=
match
(
ps
,
"CHARGE_"
);
}
if
(
!
energy
)
{
continue
;
}
const
char
*
value
=
(
!
full
)
?
match
(
energy
,
"FULL="
)
:
NULL
;
if
(
value
)
{
totalFull
+=
atoi
(
value
);
full
=
true
;
if
(
now
)
break
;
continue
;
}
value
=
(
!
now
)
?
match
(
energy
,
"NOW="
)
:
NULL
;
if
(
value
)
{
totalRemain
+=
atoi
(
value
);
now
=
true
;
if
(
full
)
break
;
continue
;
}
}
}
else
if
(
entryName
[
0
]
==
'A'
)
{
if
(
*
isOnAC
!=
AC_ERROR
)
{
continue
;
}
snprintf
((
char
*
)
filePath
,
sizeof
filePath
,
SYS_POWERSUPPLY_DIR
"/%s/online"
,
entryName
);
int
fd
=
open
(
filePath
,
O_RDONLY
);
if
(
fd
==
-
1
)
{
closedir
(
dir
);
return
;
}
char
buffer
[
2
]
=
""
;
for
(;;)
{
ssize_t
res
=
read
(
fd
,
buffer
,
1
);
if
(
res
==
-
1
&&
errno
==
EINTR
)
continue
;
break
;
}
close
(
fd
);
if
(
buffer
[
0
]
==
'0'
)
{
*
isOnAC
=
AC_ABSENT
;
}
else
if
(
buffer
[
0
]
==
'1'
)
{
*
isOnAC
=
AC_PRESENT
;
}
}
}
}
closedir
(
dir
);
*
level
=
totalFull
>
0
?
((
double
)
totalRemain
*
100
)
/
(
double
)
totalFull
:
0
;
}
const
char
ueventPath
[
50
]
;
static
enum
{
BAT_PROC
,
BAT_SYS
,
BAT_ERR
}
Battery_method
=
BAT_PROC
;
snprintf
((
char
*
)
ueventPath
,
sizeof
ueventPath
,
"%s%s/uevent"
,
power_supplyPath
,
entryName
);
static
time_t
Battery_cacheTime
=
0
;
static
double
Battery_cacheLevel
=
0
;
static
ACPresence
Battery_cacheIsOnAC
=
0
;
FILE
*
file
;
void
Battery_getData
(
double
*
level
,
ACPresence
*
isOnAC
)
{
if
((
file
=
fopen
(
ueventPath
,
"r"
))
==
NULL
)
{
time_t
now
=
time
(
NULL
);
closedir
(
power_supplyDir
);
// update battery reading is slow. Update it each 10 seconds only.
return
0
;
if
(
now
<
Battery_cacheTime
+
10
)
{
}
*
level
=
Battery_cacheLevel
;
*
isOnAC
=
Battery_cacheIsOnAC
;
return
;
}
if
((
totalFull
+=
parseUevent
(
file
,
"POWER_SUPPLY_ENERGY_FULL="
)))
{
if
(
Battery_method
==
BAT_PROC
)
{
totalRemain
+=
parseUevent
(
file
,
"POWER_SUPPLY_ENERGY_NOW="
);
Battery_getProcData
(
level
,
isOnAC
);
}
else
{
if
(
*
level
==
0
)
{
//reset file pointer
Battery_method
=
BAT_SYS
;
if
(
fseek
(
file
,
0
,
SEEK_SET
)
<
0
)
{
closedir
(
power_supplyDir
);
fclose
(
file
);
return
0
;
}
}
}
}
//Some systems have it as CHARGE instead of ENERGY.
if
(
Battery_method
==
BAT_SYS
)
{
if
((
totalFull
+=
parseUevent
(
file
,
"POWER_SUPPLY_CHARGE_FULL="
)))
{
Battery_getSysData
(
level
,
isOnAC
);
totalRemain
+=
parseUevent
(
file
,
"POWER_SUPPLY_CHARGE_NOW="
);
if
(
*
level
==
0
)
{
}
else
{
Battery_method
=
BAT_ERR
;
//reset file pointer
if
(
fseek
(
file
,
0
,
SEEK_SET
)
<
0
)
{
closedir
(
power_supplyDir
);
fclose
(
file
);
return
0
;
}
}
}
fclose
(
file
);
}
}
if
(
Battery_method
==
BAT_ERR
)
{
const
double
percent
=
totalFull
>
0
?
((
double
)
totalRemain
*
100
)
/
(
double
)
totalFull
:
0
;
*
level
=
-
1
;
closedir
(
power_supplyDir
);
*
isOnAC
=
AC_ERROR
;
return
percent
;
}
Battery_cacheLevel
=
*
level
;
Battery_cacheIsOnAC
=
*
isOnAC
;
Battery_cacheTime
=
now
;
}
}
linux/Battery.h
View file @
d2acffa5
...
@@ -15,10 +15,27 @@ Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat
...
@@ -15,10 +15,27 @@ Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat
#define _GNU_SOURCE
#define _GNU_SOURCE
#endif
#endif
ACPresence
Battery_isOnAC
();
#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply"
double
Battery_getProcBatData
();
// ----------------------------------------
// READ FROM /proc
// ----------------------------------------
double
Battery_getSysBatData
();
// This implementation reading from from /proc/acpi is really inefficient,
// but I think this is on the way out so I did not rewrite it.
// The /sys implementation below does things the right way.
// ----------------------------------------
// READ FROM /sys
// ----------------------------------------
/**
* Returns a pointer to the suffix of `str` if its beginning matches `prefix`.
* Returns NULL if the prefix does not match.
* Examples:
* match("hello world", "hello "); -> "world"
* match("hello world", "goodbye "); -> NULL
*/
void
Battery_getData
(
double
*
level
,
ACPresence
*
isOnAC
);
#endif
#endif
linux/LinuxProcess.c
View file @
d2acffa5
...
@@ -10,6 +10,7 @@ in the source distribution for its full text.
...
@@ -10,6 +10,7 @@ in the source distribution for its full text.
#include "LinuxProcess.h"
#include "LinuxProcess.h"
#include "CRT.h"
#include "CRT.h"
#include <stdlib.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/syscall.h>
...
@@ -22,8 +23,23 @@ typedef struct LinuxProcess_ {
...
@@ -22,8 +23,23 @@ typedef struct LinuxProcess_ {
IOPriority ioPriority;
IOPriority ioPriority;
} LinuxProcess;
} LinuxProcess;
#define Process_delete LinuxProcess_delete
}*/
}*/
LinuxProcess
*
LinuxProcess_new
(
Settings
*
settings
)
{
LinuxProcess
*
this
=
calloc
(
sizeof
(
LinuxProcess
),
1
);
Process_init
(
&
this
->
super
,
settings
);
return
this
;
}
void
LinuxProcess_delete
(
Object
*
cast
)
{
LinuxProcess
*
this
=
(
LinuxProcess
*
)
this
;
Object_setClass
(
this
,
Class
(
Process
));
Process_done
((
Process
*
)
cast
);
free
(
this
);
}
/*
/*
[1] Note that before kernel 2.6.26 a process that has not asked for
[1] Note that before kernel 2.6.26 a process that has not asked for
an io priority formally uses "none" as scheduling class, but the
an io priority formally uses "none" as scheduling class, but the
...
@@ -45,22 +61,23 @@ bool LinuxProcess_setIOPriority(LinuxProcess* this, IOPriority ioprio) {
...
@@ -45,22 +61,23 @@ bool LinuxProcess_setIOPriority(LinuxProcess* this, IOPriority ioprio) {
return
(
LinuxProcess_updateIOPriority
(
this
)
==
ioprio
);
return
(
LinuxProcess_updateIOPriority
(
this
)
==
ioprio
);
}
}
void
LinuxProcess_writeField
(
LinuxProcess
*
this
,
RichString
*
str
,
ProcessField
field
)
{
void
Process_writeField
(
Process
*
this
,
RichString
*
str
,
ProcessField
field
)
{
LinuxProcess
*
lp
=
(
LinuxProcess
*
)
this
;
char
buffer
[
256
];
buffer
[
255
]
=
'\0'
;
char
buffer
[
256
];
buffer
[
255
]
=
'\0'
;
int
attr
=
CRT_colors
[
DEFAULT_COLOR
];
int
attr
=
CRT_colors
[
DEFAULT_COLOR
];
int
n
=
sizeof
(
buffer
)
-
1
;
int
n
=
sizeof
(
buffer
)
-
1
;
switch
(
field
)
{
switch
(
field
)
{
case
IO_PRIORITY
:
{
case
IO_PRIORITY
:
{
int
klass
=
IOPriority_class
(
this
->
ioPriority
);
int
klass
=
IOPriority_class
(
lp
->
ioPriority
);
if
(
klass
==
IOPRIO_CLASS_NONE
)
{
if
(
klass
==
IOPRIO_CLASS_NONE
)
{
// see note [1] above
// see note [1] above
snprintf
(
buffer
,
n
,
"B%1d "
,
(
int
)
(
this
->
super
.
nice
+
20
)
/
5
);
snprintf
(
buffer
,
n
,
"B%1d "
,
(
int
)
(
this
->
nice
+
20
)
/
5
);
}
else
if
(
klass
==
IOPRIO_CLASS_BE
)
{
}
else
if
(
klass
==
IOPRIO_CLASS_BE
)
{
snprintf
(
buffer
,
n
,
"B%1d "
,
IOPriority_data
(
this
->
ioPriority
));
snprintf
(
buffer
,
n
,
"B%1d "
,
IOPriority_data
(
lp
->
ioPriority
));
}
else
if
(
klass
==
IOPRIO_CLASS_RT
)
{
}
else
if
(
klass
==
IOPRIO_CLASS_RT
)
{
attr
=
CRT_colors
[
PROCESS_HIGH_PRIORITY
];
attr
=
CRT_colors
[
PROCESS_HIGH_PRIORITY
];
snprintf
(
buffer
,
n
,
"R%1d "
,
IOPriority_data
(
this
->
ioPriority
));
snprintf
(
buffer
,
n
,
"R%1d "
,
IOPriority_data
(
lp
->
ioPriority
));
}
else
if
(
this
->
ioPriority
==
IOPriority_Idle
)
{
}
else
if
(
lp
->
ioPriority
==
IOPriority_Idle
)
{
attr
=
CRT_colors
[
PROCESS_LOW_PRIORITY
];
attr
=
CRT_colors
[
PROCESS_LOW_PRIORITY
];
snprintf
(
buffer
,
n
,
"id "
);
snprintf
(
buffer
,
n
,
"id "
);
}
else
{
}
else
{
...
@@ -69,25 +86,26 @@ void LinuxProcess_writeField(LinuxProcess* this, RichString* str, ProcessField f
...
@@ -69,25 +86,26 @@ void LinuxProcess_writeField(LinuxProcess* this, RichString* str, ProcessField f
break
;
break
;
}
}
default:
default:
snprintf
(
buffer
,
n
,
"- "
);
Process_writeDefaultField
(
this
,
str
,
field
);
return
;
}
}
RichString_append
(
str
,
attr
,
buffer
);
RichString_append
(
str
,
attr
,
buffer
);
}
}
long
Linux
Process_compare
(
const
void
*
v1
,
const
void
*
v2
)
{
long
Process_compare
(
const
void
*
v1
,
const
void
*
v2
)
{
LinuxProcess
*
p1
,
*
p2
;
LinuxProcess
*
p1
,
*
p2
;
ProcessList
*
pl
=
((
Process
*
)
v1
)
->
pl
;
Settings
*
settings
=
((
Process
*
)
v1
)
->
settings
;
if
(
pl
->
direction
==
1
)
{
if
(
settings
->
direction
==
1
)
{
p1
=
(
LinuxProcess
*
)
v1
;
p1
=
(
LinuxProcess
*
)
v1
;
p2
=
(
LinuxProcess
*
)
v2
;
p2
=
(
LinuxProcess
*
)
v2
;
}
else
{
}
else
{
p2
=
(
LinuxProcess
*
)
v1
;
p2
=
(
LinuxProcess
*
)
v1
;
p1
=
(
LinuxProcess
*
)
v2
;
p1
=
(
LinuxProcess
*
)
v2
;
}
}
switch
(
pl
->
sortKey
)
{
switch
(
settings
->
sortKey
)
{
case
IO_PRIORITY
:
case
IO_PRIORITY
:
return
LinuxProcess_effectiveIOPriority
(
p1
)
-
LinuxProcess_effectiveIOPriority
(
p2
);
return
LinuxProcess_effectiveIOPriority
(
p1
)
-
LinuxProcess_effectiveIOPriority
(
p2
);
default:
default:
return
(
p1
->
super
.
pid
-
p2
->
super
.
pid
);
return
Process_defaultCompare
(
v1
,
v2
);
}
}
}
}
linux/LinuxProcess.h
View file @
d2acffa5
...
@@ -17,6 +17,12 @@ typedef struct LinuxProcess_ {
...
@@ -17,6 +17,12 @@ typedef struct LinuxProcess_ {
IOPriority
ioPriority
;
IOPriority
ioPriority
;
}
LinuxProcess
;
}
LinuxProcess
;
#define Process_delete LinuxProcess_delete
LinuxProcess
*
LinuxProcess_new
(
Settings
*
settings
);
void
LinuxProcess_delete
(
Object
*
cast
);
/*
/*
[1] Note that before kernel 2.6.26 a process that has not asked for
[1] Note that before kernel 2.6.26 a process that has not asked for
...
@@ -32,8 +38,8 @@ IOPriority LinuxProcess_updateIOPriority(LinuxProcess* this);
...
@@ -32,8 +38,8 @@ IOPriority LinuxProcess_updateIOPriority(LinuxProcess* this);
bool
LinuxProcess_setIOPriority
(
LinuxProcess
*
this
,
IOPriority
ioprio
);
bool
LinuxProcess_setIOPriority
(
LinuxProcess
*
this
,
IOPriority
ioprio
);
void
Linux
Process_writeField
(
Linux
Process
*
this
,
RichString
*
str
,
ProcessField
field
);
void
Process_writeField
(
Process
*
this
,
RichString
*
str
,
ProcessField
field
);
long
Linux
Process_compare
(
const
void
*
v1
,
const
void
*
v2
);
long
Process_compare
(
const
void
*
v1
,
const
void
*
v2
);
#endif
#endif
linux/LinuxProcessList.c
View file @
d2acffa5
...
@@ -31,6 +31,56 @@ in the source distribution for its full text.
...
@@ -31,6 +31,56 @@ in the source distribution for its full text.
#include "ProcessList.h"
#include "ProcessList.h"
typedef struct CPUData_ {
unsigned long long int totalTime;
unsigned long long int userTime;
unsigned long long int systemTime;
unsigned long long int systemAllTime;
unsigned long long int idleAllTime;
unsigned long long int idleTime;
unsigned long long int niceTime;
unsigned long long int ioWaitTime;
unsigned long long int irqTime;
unsigned long long int softIrqTime;
unsigned long long int stealTime;
unsigned long long int guestTime;
unsigned long long int totalPeriod;
unsigned long long int userPeriod;
unsigned long long int systemPeriod;
unsigned long long int systemAllPeriod;
unsigned long long int idleAllPeriod;
unsigned long long int idlePeriod;
unsigned long long int nicePeriod;
unsigned long long int ioWaitPeriod;
unsigned long long int irqPeriod;
unsigned long long int softIrqPeriod;
unsigned long long int stealPeriod;
unsigned long long int guestPeriod;
} CPUData;
typedef struct LinuxProcessList_ {
ProcessList super;
int totalTasks;
int userlandThreads;
int kernelThreads;
int runningTasks;
CPUData* cpus;
unsigned long long int totalMem;
unsigned long long int usedMem;
unsigned long long int freeMem;
unsigned long long int sharedMem;
unsigned long long int buffersMem;
unsigned long long int cachedMem;
unsigned long long int totalSwap;
unsigned long long int usedSwap;
unsigned long long int freeSwap;
} LinuxProcessList;
#ifndef PROCDIR
#ifndef PROCDIR
#define PROCDIR "/proc"
#define PROCDIR "/proc"
#endif
#endif
...
@@ -45,9 +95,10 @@ in the source distribution for its full text.
...
@@ -45,9 +95,10 @@ in the source distribution for its full text.
}*/
}*/
ProcessList
*
ProcessList_new
(
UsersTable
*
usersTable
,
Hashtable
*
pidWhiteList
)
{
ProcessList
*
ProcessList_new
(
UsersTable
*
usersTable
,
Hashtable
*
pidWhiteList
,
uid_t
userId
)
{
ProcessList
*
this
=
calloc
(
1
,
sizeof
(
ProcessList
));
LinuxProcessList
*
this
=
calloc
(
1
,
sizeof
(
LinuxProcessList
));
ProcessList_init
(
this
,
usersTable
,
pidWhiteList
);
ProcessList
*
pl
=
&
(
this
->
super
);
ProcessList_init
(
pl
,
usersTable
,
pidWhiteList
,
userId
);
// Update CPU count:
// Update CPU count:
FILE
*
file
=
fopen
(
PROCSTATFILE
,
"r"
);
FILE
*
file
=
fopen
(
PROCSTATFILE
,
"r"
);
...
@@ -62,8 +113,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList) {
...
@@ -62,8 +113,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList) {
}
while
(
String_startsWith
(
buffer
,
"cpu"
));
}
while
(
String_startsWith
(
buffer
,
"cpu"
));
fclose
(
file
);
fclose
(
file
);
this
->
cpuCount
=
MAX
(
cpus
-
1
,
1
);
pl
->
cpuCount
=
MAX
(
cpus
-
1
,
1
);
this
->
cpus
=
re
alloc
(
this
->
cpus
,
cpus
*
sizeof
(
CPUData
));
this
->
cpus
=
c
alloc
(
cpus
,
sizeof
(
CPUData
));
for
(
int
i
=
0
;
i
<
cpus
;
i
++
)
{
for
(
int
i
=
0
;
i
<
cpus
;
i
++
)
{
this
->
cpus
[
i
].
totalTime
=
1
;
this
->
cpus
[
i
].
totalTime
=
1
;
...
@@ -74,11 +125,13 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList) {
...
@@ -74,11 +125,13 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList) {
this
->
flags
|=
PROCESS_FLAG_OPENVZ
;
this
->
flags
|=
PROCESS_FLAG_OPENVZ
;
#endif
#endif
return
this
;
return
pl
;
}
}
void
ProcessList_delete
(
ProcessList
*
this
)
{
void
ProcessList_delete
(
ProcessList
*
pl
)
{
ProcessList_done
(
this
);
LinuxProcessList
*
this
=
(
LinuxProcessList
*
)
pl
;
ProcessList_done
(
pl
);
free
(
this
->
cpus
);
free
(
this
);
free
(
this
);
}
}
...
@@ -166,7 +219,6 @@ static bool LinuxProcessList_readStatFile(Process *process, const char* dirname,
...
@@ -166,7 +219,6 @@ static bool LinuxProcessList_readStatFile(Process *process, const char* dirname,
location
+=
1
;
location
+=
1
;
assert
(
location
!=
NULL
);
assert
(
location
!=
NULL
);
process
->
processor
=
strtol
(
location
,
&
location
,
10
);
process
->
processor
=
strtol
(
location
,
&
location
,
10
);
assert
(
location
==
NULL
);
return
true
;
return
true
;
}
}
...
@@ -200,8 +252,11 @@ static void LinuxProcessList_readIoFile(Process* process, const char* dirname, c
...
@@ -200,8 +252,11 @@ static void LinuxProcessList_readIoFile(Process* process, const char* dirname, c
snprintf
(
filename
,
MAX_NAME
,
"%s/%s/io"
,
dirname
,
name
);
snprintf
(
filename
,
MAX_NAME
,
"%s/%s/io"
,
dirname
,
name
);
int
fd
=
open
(
filename
,
O_RDONLY
);
int
fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
==
-
1
)
if
(
fd
==
-
1
)
{
process
->
io_rate_read_bps
=
-
1
;
process
->
io_rate_write_bps
=
-
1
;
return
;
return
;
}
char
buffer
[
1024
];
char
buffer
[
1024
];
ssize_t
buflen
=
xread
(
fd
,
buffer
,
1023
);
ssize_t
buflen
=
xread
(
fd
,
buffer
,
1023
);
...
@@ -289,7 +344,7 @@ static void LinuxProcessList_readOpenVZData(ProcessList* this, Process* process,
...
@@ -289,7 +344,7 @@ static void LinuxProcessList_readOpenVZData(ProcessList* this, Process* process,
FILE
*
file
=
fopen
(
filename
,
"r"
);
FILE
*
file
=
fopen
(
filename
,
"r"
);
if
(
!
file
)
if
(
!
file
)
return
;
return
;
fscanf
(
file
,
(
void
)
fscanf
(
file
,
"%*32u %*32s %*1c %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
"%*32u %*32s %*1c %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
"%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
"%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
"%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
"%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
...
@@ -320,6 +375,7 @@ static void LinuxProcessList_readCGroupFile(Process* process, const char* dirnam
...
@@ -320,6 +375,7 @@ static void LinuxProcessList_readCGroupFile(Process* process, const char* dirnam
int
nFields
;
int
nFields
;
char
**
fields
=
String_split
(
trimmed
,
':'
,
&
nFields
);
char
**
fields
=
String_split
(
trimmed
,
':'
,
&
nFields
);
free
(
trimmed
);
free
(
trimmed
);
free
(
process
->
cgroup
);
if
(
nFields
>=
3
)
{
if
(
nFields
>=
3
)
{
process
->
cgroup
=
strndup
(
fields
[
2
]
+
1
,
10
);
process
->
cgroup
=
strndup
(
fields
[
2
]
+
1
,
10
);
}
else
{
}
else
{
...
@@ -420,9 +476,10 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, const char* dirna
...
@@ -420,9 +476,10 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, const char* dirna
return
true
;
return
true
;
}
}
static
bool
LinuxProcessList_processEntries
(
ProcessList
*
this
,
const
char
*
dirname
,
Process
*
parent
,
double
period
,
struct
timeval
tv
)
{
static
bool
LinuxProcessList_processEntries
(
Linux
ProcessList
*
this
,
const
char
*
dirname
,
Process
*
parent
,
double
period
,
struct
timeval
tv
)
{
DIR
*
dir
;
DIR
*
dir
;
struct
dirent
*
entry
;
struct
dirent
*
entry
;
Settings
*
settings
=
this
->
super
.
settings
;
time_t
curTime
=
tv
.
tv_sec
;
time_t
curTime
=
tv
.
tv_sec
;
#ifdef HAVE_TASKSTATS
#ifdef HAVE_TASKSTATS
...
@@ -431,15 +488,15 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
...
@@ -431,15 +488,15 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
dir
=
opendir
(
dirname
);
dir
=
opendir
(
dirname
);
if
(
!
dir
)
return
false
;
if
(
!
dir
)
return
false
;
int
cpus
=
this
->
cpuCount
;
int
cpus
=
this
->
super
.
cpuCount
;
bool
hideKernelThreads
=
thi
s
->
hideKernelThreads
;
bool
hideKernelThreads
=
setting
s
->
hideKernelThreads
;
bool
hideUserlandThreads
=
thi
s
->
hideUserlandThreads
;
bool
hideUserlandThreads
=
setting
s
->
hideUserlandThreads
;
while
((
entry
=
readdir
(
dir
))
!=
NULL
)
{
while
((
entry
=
readdir
(
dir
))
!=
NULL
)
{
char
*
name
=
entry
->
d_name
;
char
*
name
=
entry
->
d_name
;
// The RedHat kernel hides threads with a dot.
// The RedHat kernel hides threads with a dot.
// I believe this is non-standard.
// I believe this is non-standard.
if
((
!
thi
s
->
hideThreads
)
&&
name
[
0
]
==
'.'
)
{
if
((
!
setting
s
->
hideThreads
)
&&
name
[
0
]
==
'.'
)
{
name
++
;
name
++
;
}
}
...
@@ -458,14 +515,14 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
...
@@ -458,14 +515,14 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
continue
;
continue
;
Process
*
process
=
NULL
;
Process
*
process
=
NULL
;
Process
*
existingProcess
=
(
Process
*
)
Hashtable_get
(
this
->
processTable
,
pid
);
Process
*
existingProcess
=
(
Process
*
)
Hashtable_get
(
this
->
super
.
processTable
,
pid
);
if
(
existingProcess
)
{
if
(
existingProcess
)
{
assert
(
Vector_indexOf
(
this
->
processes
,
existingProcess
,
Process_pidCompare
)
!=
-
1
);
assert
(
Vector_indexOf
(
this
->
processes
,
existingProcess
,
Process_pidCompare
)
!=
-
1
);
process
=
existingProcess
;
process
=
existingProcess
;
assert
(
process
->
pid
==
pid
);
assert
(
process
->
pid
==
pid
);
}
else
{
}
else
{
process
=
Process_new
(
thi
s
);
process
=
(
Process
*
)
Linux
Process_new
(
setting
s
);
assert
(
process
->
comm
==
NULL
);
assert
(
process
->
comm
==
NULL
);
process
->
pid
=
pid
;
process
->
pid
=
pid
;
process
->
tgid
=
parent
?
parent
->
pid
:
pid
;
process
->
tgid
=
parent
?
parent
->
pid
:
pid
;
...
@@ -476,7 +533,7 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
...
@@ -476,7 +533,7 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
LinuxProcessList_processEntries
(
this
,
subdirname
,
process
,
period
,
tv
);
LinuxProcessList_processEntries
(
this
,
subdirname
,
process
,
period
,
tv
);
#ifdef HAVE_TASKSTATS
#ifdef HAVE_TASKSTATS
if
(
thi
s
->
flags
&
PROCESS_FLAG_IO
)
if
(
setting
s
->
flags
&
PROCESS_FLAG_IO
)
LinuxProcessList_readIoFile
(
process
,
dirname
,
name
,
now
);
LinuxProcessList_readIoFile
(
process
,
dirname
,
name
,
now
);
#endif
#endif
...
@@ -489,7 +546,7 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
...
@@ -489,7 +546,7 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
unsigned
long
long
int
lasttimes
=
(
process
->
utime
+
process
->
stime
);
unsigned
long
long
int
lasttimes
=
(
process
->
utime
+
process
->
stime
);
if
(
!
LinuxProcessList_readStatFile
(
process
,
dirname
,
name
,
command
))
if
(
!
LinuxProcessList_readStatFile
(
process
,
dirname
,
name
,
command
))
goto
errorReadingProcess
;
goto
errorReadingProcess
;
if
(
thi
s
->
flags
&
PROCESS_FLAG_IOPRIO
)
if
(
setting
s
->
flags
&
PROCESS_FLAG_IOPRIO
)
LinuxProcess_updateIOPriority
((
LinuxProcess
*
)
process
);
LinuxProcess_updateIOPriority
((
LinuxProcess
*
)
process
);
float
percent_cpu
=
(
process
->
utime
+
process
->
stime
-
lasttimes
)
/
period
*
100
.
0
;
float
percent_cpu
=
(
process
->
utime
+
process
->
stime
-
lasttimes
)
/
period
*
100
.
0
;
process
->
percent_cpu
=
MAX
(
MIN
(
percent_cpu
,
cpus
*
100
.
0
),
0
.
0
);
process
->
percent_cpu
=
MAX
(
MIN
(
percent_cpu
,
cpus
*
100
.
0
),
0
.
0
);
...
@@ -501,30 +558,30 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
...
@@ -501,30 +558,30 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
if
(
!
LinuxProcessList_statProcessDir
(
process
,
dirname
,
name
,
curTime
))
if
(
!
LinuxProcessList_statProcessDir
(
process
,
dirname
,
name
,
curTime
))
goto
errorReadingProcess
;
goto
errorReadingProcess
;
process
->
user
=
UsersTable_getRef
(
this
->
usersTable
,
process
->
st_uid
);
process
->
user
=
UsersTable_getRef
(
this
->
super
.
usersTable
,
process
->
st_uid
);
#ifdef HAVE_OPENVZ
#ifdef HAVE_OPENVZ
LinuxProcessList_readOpenVZData
(
this
,
process
,
dirname
,
name
);
LinuxProcessList_readOpenVZData
(
this
,
process
,
dirname
,
name
);
#endif
#endif
#ifdef HAVE_VSERVER
#ifdef HAVE_VSERVER
if
(
thi
s
->
flags
&
PROCESS_FLAG_VSERVER
)
if
(
setting
s
->
flags
&
PROCESS_FLAG_VSERVER
)
LinuxProcessList_readVServerData
(
process
,
dirname
,
name
);
LinuxProcessList_readVServerData
(
process
,
dirname
,
name
);
#endif
#endif
if
(
!
LinuxProcessList_readCmdlineFile
(
process
,
dirname
,
name
))
if
(
!
LinuxProcessList_readCmdlineFile
(
process
,
dirname
,
name
))
goto
errorReadingProcess
;
goto
errorReadingProcess
;
ProcessList_add
(
this
,
process
);
ProcessList_add
(
(
ProcessList
*
)
this
,
process
);
}
else
{
}
else
{
if
(
thi
s
->
updateProcessNames
)
{
if
(
setting
s
->
updateProcessNames
)
{
if
(
!
LinuxProcessList_readCmdlineFile
(
process
,
dirname
,
name
))
if
(
!
LinuxProcessList_readCmdlineFile
(
process
,
dirname
,
name
))
goto
errorReadingProcess
;
goto
errorReadingProcess
;
}
}
}
}
#ifdef HAVE_CGROUP
#ifdef HAVE_CGROUP
if
(
thi
s
->
flags
&
PROCESS_FLAG_CGROUP
)
if
(
setting
s
->
flags
&
PROCESS_FLAG_CGROUP
)
LinuxProcessList_readCGroupFile
(
process
,
dirname
,
name
);
LinuxProcessList_readCGroupFile
(
process
,
dirname
,
name
);
#endif
#endif
...
@@ -537,11 +594,11 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
...
@@ -537,11 +594,11 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
process
->
basenameOffset
=
-
1
;
process
->
basenameOffset
=
-
1
;
process
->
comm
=
strdup
(
command
);
process
->
comm
=
strdup
(
command
);
}
else
if
(
Process_isThread
(
process
))
{
}
else
if
(
Process_isThread
(
process
))
{
if
(
thi
s
->
showThreadNames
||
Process_isKernelThread
(
process
)
||
process
->
state
==
'Z'
)
{
if
(
setting
s
->
showThreadNames
||
Process_isKernelThread
(
process
)
||
process
->
state
==
'Z'
)
{
free
(
process
->
comm
);
free
(
process
->
comm
);
process
->
basenameOffset
=
-
1
;
process
->
basenameOffset
=
-
1
;
process
->
comm
=
strdup
(
command
);
process
->
comm
=
strdup
(
command
);
}
else
if
(
thi
s
->
show
ing
ThreadNames
)
{
}
else
if
(
setting
s
->
showThreadNames
)
{
if
(
!
LinuxProcessList_readCmdlineFile
(
process
,
dirname
,
name
))
if
(
!
LinuxProcessList_readCmdlineFile
(
process
,
dirname
,
name
))
goto
errorReadingProcess
;
goto
errorReadingProcess
;
}
}
...
@@ -567,16 +624,16 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
...
@@ -567,16 +624,16 @@ static bool LinuxProcessList_processEntries(ProcessList* this, const char* dirna
process
->
comm
=
NULL
;
process
->
comm
=
NULL
;
}
}
if
(
existingProcess
)
if
(
existingProcess
)
ProcessList_remove
(
this
,
process
);
ProcessList_remove
(
(
ProcessList
*
)
this
,
process
);
else
else
Process_delete
((
Object
*
)
process
);
Linux
Process_delete
((
Object
*
)
process
);
}
}
}
}
closedir
(
dir
);
closedir
(
dir
);
return
true
;
return
true
;
}
}
static
inline
void
LinuxProcessList_scanMemoryInfo
(
ProcessList
*
this
)
{
static
inline
void
LinuxProcessList_scanMemoryInfo
(
Linux
ProcessList
*
this
)
{
unsigned
long
long
int
swapFree
=
0
;
unsigned
long
long
int
swapFree
=
0
;
FILE
*
file
=
fopen
(
PROCMEMINFOFILE
,
"r"
);
FILE
*
file
=
fopen
(
PROCMEMINFOFILE
,
"r"
);
...
@@ -617,14 +674,14 @@ static inline void LinuxProcessList_scanMemoryInfo(ProcessList* this) {
...
@@ -617,14 +674,14 @@ static inline void LinuxProcessList_scanMemoryInfo(ProcessList* this) {
fclose
(
file
);
fclose
(
file
);
}
}
static
inline
double
LinuxProcessList_scanCPUTime
(
ProcessList
*
this
)
{
static
inline
double
LinuxProcessList_scanCPUTime
(
Linux
ProcessList
*
this
)
{
unsigned
long
long
int
usertime
,
nicetime
,
systemtime
,
idletime
;
unsigned
long
long
int
usertime
,
nicetime
,
systemtime
,
idletime
;
FILE
*
file
=
fopen
(
PROCSTATFILE
,
"r"
);
FILE
*
file
=
fopen
(
PROCSTATFILE
,
"r"
);
if
(
file
==
NULL
)
{
if
(
file
==
NULL
)
{
CRT_fatalError
(
"Cannot open "
PROCSTATFILE
);
CRT_fatalError
(
"Cannot open "
PROCSTATFILE
);
}
}
int
cpus
=
this
->
cpuCount
;
int
cpus
=
this
->
super
.
cpuCount
;
assert
(
cpus
>
0
);
assert
(
cpus
>
0
);
for
(
int
i
=
0
;
i
<=
cpus
;
i
++
)
{
for
(
int
i
=
0
;
i
<=
cpus
;
i
++
)
{
char
buffer
[
256
];
char
buffer
[
256
];
...
@@ -635,7 +692,8 @@ static inline double LinuxProcessList_scanCPUTime(ProcessList* this) {
...
@@ -635,7 +692,8 @@ static inline double LinuxProcessList_scanCPUTime(ProcessList* this) {
// Dependending on your kernel version,
// Dependending on your kernel version,
// 5, 7, 8 or 9 of these fields will be set.
// 5, 7, 8 or 9 of these fields will be set.
// The rest will remain at zero.
// The rest will remain at zero.
fgets
(
buffer
,
255
,
file
);
char
*
ok
=
fgets
(
buffer
,
255
,
file
);
if
(
!
ok
)
buffer
[
0
]
=
'\0'
;
if
(
i
==
0
)
if
(
i
==
0
)
sscanf
(
buffer
,
"cpu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu"
,
&
usertime
,
&
nicetime
,
&
systemtime
,
&
idletime
,
&
ioWait
,
&
irq
,
&
softIrq
,
&
steal
,
&
guest
,
&
guestnice
);
sscanf
(
buffer
,
"cpu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu"
,
&
usertime
,
&
nicetime
,
&
systemtime
,
&
idletime
,
&
ioWait
,
&
irq
,
&
softIrq
,
&
steal
,
&
guest
,
&
guestnice
);
else
{
else
{
...
@@ -693,15 +751,16 @@ static inline double LinuxProcessList_scanCPUTime(ProcessList* this) {
...
@@ -693,15 +751,16 @@ static inline double LinuxProcessList_scanCPUTime(ProcessList* this) {
return
period
;
return
period
;
}
}
void
ProcessList_scan
(
ProcessList
*
this
)
{
void
ProcessList_scan
(
ProcessList
*
super
)
{
LinuxProcessList
*
this
=
(
LinuxProcessList
*
)
super
;
LinuxProcessList_scanMemoryInfo
(
this
);
LinuxProcessList_scanMemoryInfo
(
this
);
double
period
=
LinuxProcessList_scanCPUTime
(
this
);
double
period
=
LinuxProcessList_scanCPUTime
(
this
);
// mark all process as "dirty"
// mark all process as "dirty"
for
(
int
i
=
0
;
i
<
Vector_size
(
this
->
processes
);
i
++
)
{
for
(
int
i
=
0
;
i
<
Vector_size
(
super
->
processes
);
i
++
)
{
Process
*
p
=
(
Process
*
)
Vector_get
(
this
->
processes
,
i
);
Process
*
p
=
(
Process
*
)
Vector_get
(
super
->
processes
,
i
);
p
->
updated
=
false
;
p
->
updated
=
false
;
}
}
...
@@ -714,12 +773,10 @@ void ProcessList_scan(ProcessList* this) {
...
@@ -714,12 +773,10 @@ void ProcessList_scan(ProcessList* this) {
gettimeofday
(
&
tv
,
NULL
);
gettimeofday
(
&
tv
,
NULL
);
LinuxProcessList_processEntries
(
this
,
PROCDIR
,
NULL
,
period
,
tv
);
LinuxProcessList_processEntries
(
this
,
PROCDIR
,
NULL
,
period
,
tv
);
this
->
showingThreadNames
=
this
->
showThreadNames
;
for
(
int
i
=
Vector_size
(
this
->
super
.
processes
)
-
1
;
i
>=
0
;
i
--
)
{
Process
*
p
=
(
Process
*
)
Vector_get
(
this
->
super
.
processes
,
i
);
for
(
int
i
=
Vector_size
(
this
->
processes
)
-
1
;
i
>=
0
;
i
--
)
{
Process
*
p
=
(
Process
*
)
Vector_get
(
this
->
processes
,
i
);
if
(
p
->
updated
==
false
)
if
(
p
->
updated
==
false
)
ProcessList_remove
(
this
,
p
);
ProcessList_remove
(
super
,
p
);
else
else
p
->
updated
=
false
;
p
->
updated
=
false
;
}
}
...
...
linux/LinuxProcessList.h
View file @
d2acffa5
...
@@ -12,6 +12,56 @@ in the source distribution for its full text.
...
@@ -12,6 +12,56 @@ in the source distribution for its full text.
#include "ProcessList.h"
#include "ProcessList.h"
typedef
struct
CPUData_
{
unsigned
long
long
int
totalTime
;
unsigned
long
long
int
userTime
;
unsigned
long
long
int
systemTime
;
unsigned
long
long
int
systemAllTime
;
unsigned
long
long
int
idleAllTime
;
unsigned
long
long
int
idleTime
;
unsigned
long
long
int
niceTime
;
unsigned
long
long
int
ioWaitTime
;
unsigned
long
long
int
irqTime
;
unsigned
long
long
int
softIrqTime
;
unsigned
long
long
int
stealTime
;
unsigned
long
long
int
guestTime
;
unsigned
long
long
int
totalPeriod
;
unsigned
long
long
int
userPeriod
;
unsigned
long
long
int
systemPeriod
;
unsigned
long
long
int
systemAllPeriod
;
unsigned
long
long
int
idleAllPeriod
;
unsigned
long
long
int
idlePeriod
;
unsigned
long
long
int
nicePeriod
;
unsigned
long
long
int
ioWaitPeriod
;
unsigned
long
long
int
irqPeriod
;
unsigned
long
long
int
softIrqPeriod
;
unsigned
long
long
int
stealPeriod
;
unsigned
long
long
int
guestPeriod
;
}
CPUData
;
typedef
struct
LinuxProcessList_
{
ProcessList
super
;
int
totalTasks
;
int
userlandThreads
;
int
kernelThreads
;
int
runningTasks
;
CPUData
*
cpus
;
unsigned
long
long
int
totalMem
;
unsigned
long
long
int
usedMem
;
unsigned
long
long
int
freeMem
;
unsigned
long
long
int
sharedMem
;
unsigned
long
long
int
buffersMem
;
unsigned
long
long
int
cachedMem
;
unsigned
long
long
int
totalSwap
;
unsigned
long
long
int
usedSwap
;
unsigned
long
long
int
freeSwap
;
}
LinuxProcessList
;
#ifndef PROCDIR
#ifndef PROCDIR
#define PROCDIR "/proc"
#define PROCDIR "/proc"
#endif
#endif
...
@@ -25,9 +75,9 @@ in the source distribution for its full text.
...
@@ -25,9 +75,9 @@ in the source distribution for its full text.
#endif
#endif
ProcessList
*
ProcessList_new
(
UsersTable
*
usersTable
,
Hashtable
*
pidWhiteList
);
ProcessList
*
ProcessList_new
(
UsersTable
*
usersTable
,
Hashtable
*
pidWhiteList
,
uid_t
userId
);
void
ProcessList_delete
(
ProcessList
*
this
);
void
ProcessList_delete
(
ProcessList
*
pl
);
#ifdef HAVE_TASKSTATS
#ifdef HAVE_TASKSTATS
...
@@ -50,7 +100,7 @@ void ProcessList_delete(ProcessList* this);
...
@@ -50,7 +100,7 @@ void ProcessList_delete(ProcessList* this);
#endif
#endif
void
ProcessList_scan
(
ProcessList
*
this
);
void
ProcessList_scan
(
ProcessList
*
super
);
#endif
#endif
linux/Platform.c
View file @
d2acffa5
...
@@ -9,6 +9,7 @@ in the source distribution for its full text.
...
@@ -9,6 +9,7 @@ in the source distribution for its full text.
#include "IOPriority.h"
#include "IOPriority.h"
#include "IOPriorityPanel.h"
#include "IOPriorityPanel.h"
#include "LinuxProcess.h"
#include "LinuxProcess.h"
#include "LinuxProcessList.h"
#include "Battery.h"
#include "Battery.h"
#include "Meter.h"
#include "Meter.h"
...
@@ -26,20 +27,23 @@ in the source distribution for its full text.
...
@@ -26,20 +27,23 @@ in the source distribution for its full text.
/*{
/*{
#include "Action.h"
#include "Action.h"
#include "MainPanel.h"
#include "BatteryMeter.h"
#include "BatteryMeter.h"
#include "LinuxProcess.h"
}*/
}*/
static
Htop_Reaction
Platform_actionSetIOPriority
(
Panel
*
panel
,
ProcessList
*
pl
,
Header
*
header
)
{
static
Htop_Reaction
Platform_actionSetIOPriority
(
State
*
st
)
{
(
void
)
panel
,
(
void
)
pl
;
Panel
*
panel
=
st
->
panel
;
LinuxProcess
*
p
=
(
LinuxProcess
*
)
Panel_getSelected
(
panel
);
LinuxProcess
*
p
=
(
LinuxProcess
*
)
Panel_getSelected
(
panel
);
if
(
!
p
)
return
HTOP_OK
;
if
(
!
p
)
return
HTOP_OK
;
IOPriority
ioprio
=
p
->
ioPriority
;
IOPriority
ioprio
=
p
->
ioPriority
;
Panel
*
ioprioPanel
=
IOPriorityPanel_new
(
ioprio
);
Panel
*
ioprioPanel
=
IOPriorityPanel_new
(
ioprio
);
const
char
*
fuFunctions
[]
=
{
"Set "
,
"Cancel "
,
NULL
};
const
char
*
fuFunctions
[]
=
{
"Set "
,
"Cancel "
,
NULL
};
void
*
set
=
Action_pickFromVector
(
panel
,
ioprioPanel
,
21
,
fuFunctions
,
header
);
void
*
set
=
Action_pickFromVector
(
st
,
ioprioPanel
,
21
,
fuFunctions
);
if
(
set
)
{
if
(
set
)
{
IOPriority
ioprio
=
IOPriorityPanel_getIOPriority
(
ioprioPanel
);
IOPriority
ioprio
=
IOPriorityPanel_getIOPriority
(
ioprioPanel
);
bool
ok
=
Action
_foreachProcess
(
panel
,
(
Action
_ForeachProcessFn
)
LinuxProcess_setIOPriority
,
(
size_t
)
ioprio
,
NULL
);
bool
ok
=
MainPanel
_foreachProcess
(
(
MainPanel
*
)
panel
,
(
MainPanel
_ForeachProcessFn
)
LinuxProcess_setIOPriority
,
(
size_t
)
ioprio
,
NULL
);
if
(
!
ok
)
if
(
!
ok
)
beep
();
beep
();
}
}
...
@@ -76,8 +80,9 @@ int Platform_getUptime() {
...
@@ -76,8 +80,9 @@ int Platform_getUptime() {
double
uptime
=
0
;
double
uptime
=
0
;
FILE
*
fd
=
fopen
(
PROCDIR
"/uptime"
,
"r"
);
FILE
*
fd
=
fopen
(
PROCDIR
"/uptime"
,
"r"
);
if
(
fd
)
{
if
(
fd
)
{
fscanf
(
fd
,
"%64lf"
,
&
uptime
);
int
n
=
fscanf
(
fd
,
"%64lf"
,
&
uptime
);
fclose
(
fd
);
fclose
(
fd
);
if
(
n
<=
0
)
return
0
;
}
}
return
(
int
)
floor
(
uptime
);
return
(
int
)
floor
(
uptime
);
}
}
...
@@ -99,24 +104,67 @@ int Platform_getMaxPid() {
...
@@ -99,24 +104,67 @@ int Platform_getMaxPid() {
FILE
*
file
=
fopen
(
PROCDIR
"/sys/kernel/pid_max"
,
"r"
);
FILE
*
file
=
fopen
(
PROCDIR
"/sys/kernel/pid_max"
,
"r"
);
if
(
!
file
)
return
-
1
;
if
(
!
file
)
return
-
1
;
int
maxPid
=
4194303
;
int
maxPid
=
4194303
;
fscanf
(
file
,
"%32d"
,
&
maxPid
);
(
void
)
fscanf
(
file
,
"%32d"
,
&
maxPid
);
fclose
(
file
);
fclose
(
file
);
return
maxPid
;
return
maxPid
;
}
}
void
Platform_getBatteryLevel
(
double
*
level
,
ACPresence
*
isOnAC
)
{
double
Platform_setCPUValues
(
Meter
*
this
,
int
cpu
)
{
LinuxProcessList
*
pl
=
(
LinuxProcessList
*
)
this
->
pl
;
CPUData
*
cpuData
=
&
(
pl
->
cpus
[
cpu
]);
double
total
=
(
double
)
(
cpuData
->
totalPeriod
==
0
?
1
:
cpuData
->
totalPeriod
);
double
percent
;
double
*
v
=
this
->
values
;
v
[
0
]
=
cpuData
->
nicePeriod
/
total
*
100
.
0
;
v
[
1
]
=
cpuData
->
userPeriod
/
total
*
100
.
0
;
if
(
this
->
pl
->
settings
->
detailedCPUTime
)
{
v
[
2
]
=
cpuData
->
systemPeriod
/
total
*
100
.
0
;
v
[
3
]
=
cpuData
->
irqPeriod
/
total
*
100
.
0
;
v
[
4
]
=
cpuData
->
softIrqPeriod
/
total
*
100
.
0
;
v
[
5
]
=
cpuData
->
stealPeriod
/
total
*
100
.
0
;
v
[
6
]
=
cpuData
->
guestPeriod
/
total
*
100
.
0
;
v
[
7
]
=
cpuData
->
ioWaitPeriod
/
total
*
100
.
0
;
Meter_setItems
(
this
,
8
);
if
(
this
->
pl
->
settings
->
accountGuestInCPUMeter
)
{
percent
=
v
[
0
]
+
v
[
1
]
+
v
[
2
]
+
v
[
3
]
+
v
[
4
]
+
v
[
5
]
+
v
[
6
];
}
else
{
percent
=
v
[
0
]
+
v
[
1
]
+
v
[
2
]
+
v
[
3
]
+
v
[
4
];
}
}
else
{
v
[
2
]
=
cpuData
->
systemAllPeriod
/
total
*
100
.
0
;
v
[
3
]
=
(
cpuData
->
stealPeriod
+
cpuData
->
guestPeriod
)
/
total
*
100
.
0
;
Meter_setItems
(
this
,
4
);
percent
=
v
[
0
]
+
v
[
1
]
+
v
[
2
]
+
v
[
3
];
}
percent
=
MIN
(
100
.
0
,
MAX
(
0
.
0
,
percent
));
if
(
isnan
(
percent
))
percent
=
0
.
0
;
return
percent
;
}
double
percent
=
Battery_getProcBatData
();
void
Platform_setMemoryValues
(
Meter
*
this
)
{
LinuxProcessList
*
pl
=
(
LinuxProcessList
*
)
this
->
pl
;
long
int
usedMem
=
pl
->
usedMem
;
long
int
buffersMem
=
pl
->
buffersMem
;
long
int
cachedMem
=
pl
->
cachedMem
;
usedMem
-=
buffersMem
+
cachedMem
;
this
->
total
=
pl
->
totalMem
;
this
->
values
[
0
]
=
usedMem
;
this
->
values
[
1
]
=
buffersMem
;
this
->
values
[
2
]
=
cachedMem
;
}
if
(
percent
==
0
)
{
void
Platform_setSwapValues
(
Meter
*
this
)
{
percent
=
Battery_getSysBatData
();
LinuxProcessList
*
pl
=
(
LinuxProcessList
*
)
this
->
pl
;
if
(
percent
==
0
)
{
this
->
total
=
pl
->
totalSwap
;
*
level
=
-
1
;
this
->
values
[
0
]
=
pl
->
usedSwap
;
*
isOnAC
=
AC_ERROR
;
}
return
;
}
}
*
isOnAC
=
Battery_isOnAC
();
void
Platform_setTasksValues
(
Meter
*
this
)
{
*
level
=
percent
;
LinuxProcessList
*
pl
=
(
LinuxProcessList
*
)
this
->
pl
;
this
->
values
[
0
]
=
pl
->
kernelThreads
;
this
->
values
[
1
]
=
pl
->
userlandThreads
;
this
->
values
[
2
]
=
pl
->
totalTasks
-
pl
->
kernelThreads
-
pl
->
userlandThreads
;
this
->
values
[
3
]
=
pl
->
runningTasks
;
if
(
pl
->
totalTasks
>
this
->
total
)
this
->
total
=
pl
->
totalTasks
;
}
}
linux/Platform.h
View file @
d2acffa5
...
@@ -10,7 +10,9 @@ in the source distribution for its full text.
...
@@ -10,7 +10,9 @@ in the source distribution for its full text.
*/
*/
#include "Action.h"
#include "Action.h"
#include "MainPanel.h"
#include "BatteryMeter.h"
#include "BatteryMeter.h"
#include "LinuxProcess.h"
void
Platform_setBindings
(
Htop_Action
*
keys
);
void
Platform_setBindings
(
Htop_Action
*
keys
);
...
@@ -22,6 +24,12 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen);
...
@@ -22,6 +24,12 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen);
int
Platform_getMaxPid
();
int
Platform_getMaxPid
();
void
Platform_getBatteryLevel
(
double
*
level
,
ACPresence
*
isOnAC
);
double
Platform_setCPUValues
(
Meter
*
this
,
int
cpu
);
void
Platform_setMemoryValues
(
Meter
*
this
);
void
Platform_setSwapValues
(
Meter
*
this
);
void
Platform_setTasksValues
(
Meter
*
this
);
#endif
#endif
scripts/MakeHeader.py
View file @
d2acffa5
...
@@ -56,6 +56,8 @@ for line in file.readlines():
...
@@ -56,6 +56,8 @@ for line in file.readlines():
state
=
SKIP
state
=
SKIP
elif
equals
!=
-
1
:
elif
equals
!=
-
1
:
out
.
write
(
"extern "
+
line
[:
equals
]
+
";"
)
out
.
write
(
"extern "
+
line
[:
equals
]
+
";"
)
elif
line
.
startswith
(
"typedef struct"
):
state
=
SKIP
elif
line
[
-
1
]
==
"{"
:
elif
line
[
-
1
]
==
"{"
:
out
.
write
(
line
[:
-
2
].
replace
(
"inline"
,
"extern"
)
+
";"
)
out
.
write
(
line
[:
-
2
].
replace
(
"inline"
,
"extern"
)
+
";"
)
state
=
SKIP
state
=
SKIP
...
...
unsupported/Platform.c
View file @
d2acffa5
...
@@ -18,6 +18,7 @@ in the source distribution for its full text.
...
@@ -18,6 +18,7 @@ in the source distribution for its full text.
/*{
/*{
#include "Action.h"
#include "Action.h"
#include "BatteryMeter.h"
#include "BatteryMeter.h"
#include "UnsupportedProcess.h"
}*/
}*/
void
Platform_setBindings
(
Htop_Action
*
keys
)
{
void
Platform_setBindings
(
Htop_Action
*
keys
)
{
...
@@ -59,8 +60,3 @@ int Platform_getMaxPid() {
...
@@ -59,8 +60,3 @@ int Platform_getMaxPid() {
return
-
1
;
return
-
1
;
}
}
void
Platform_getBatteryLevel
(
double
*
level
,
ACPresence
*
isOnAC
)
{
*
level
=
-
1
;
*
isOnAC
=
AC_ERROR
;
}
unsupported/Platform.h
View file @
d2acffa5
...
@@ -10,6 +10,8 @@ in the source distribution for its full text.
...
@@ -10,6 +10,8 @@ in the source distribution for its full text.
*/
*/
#include "Action.h"
#include "Action.h"
#include "BatteryMeter.h"
#include "UnsupportedProcess.h"
void
Platform_setBindings
(
Htop_Action
*
keys
);
void
Platform_setBindings
(
Htop_Action
*
keys
);
...
@@ -19,4 +21,6 @@ int Platform_getUptime();
...
@@ -19,4 +21,6 @@ int Platform_getUptime();
void
Platform_getLoadAverage
(
double
*
one
,
double
*
five
,
double
*
fifteen
);
void
Platform_getLoadAverage
(
double
*
one
,
double
*
five
,
double
*
fifteen
);
int
Platform_getMaxPid
();
#endif
#endif
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment