diff options
author | Ron Yorston <rmy@pobox.com> | 2017-09-01 17:50:39 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2017-09-01 18:00:01 +0100 |
commit | dd9f552bb1fee66f3155bbbb81c677def861ada0 (patch) | |
tree | 21c7f1f333a2a58361c813311188b286ea803c9c | |
parent | ec3ecac715b299766c101be92caf8b7cffb2a8b5 (diff) | |
download | busybox-w32-dd9f552bb1fee66f3155bbbb81c677def861ada0.tar.gz busybox-w32-dd9f552bb1fee66f3155bbbb81c677def861ada0.tar.bz2 busybox-w32-dd9f552bb1fee66f3155bbbb81c677def861ada0.zip |
ps: add support for CPU and elapsed time columns
It may be necessary to run ps as administrator to get information
about processes belonging to other users.
The code to detect GetTickCount64 at run-time was imported from
Git for Windows.
-rw-r--r-- | configs/mingw32_defconfig | 2 | ||||
-rw-r--r-- | configs/mingw64_defconfig | 2 | ||||
-rw-r--r-- | include/mingw.h | 7 | ||||
-rw-r--r-- | procps/ps.c | 7 | ||||
-rw-r--r-- | win32/lazyload.h | 43 | ||||
-rw-r--r-- | win32/mingw.c | 18 | ||||
-rw-r--r-- | win32/process.c | 47 |
7 files changed, 119 insertions, 7 deletions
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index abe56f619..3a30cf366 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -991,7 +991,7 @@ CONFIG_FEATURE_PIDOF_OMIT=y | |||
991 | CONFIG_PS=y | 991 | CONFIG_PS=y |
992 | # CONFIG_FEATURE_PS_WIDE is not set | 992 | # CONFIG_FEATURE_PS_WIDE is not set |
993 | # CONFIG_FEATURE_PS_LONG is not set | 993 | # CONFIG_FEATURE_PS_LONG is not set |
994 | # CONFIG_FEATURE_PS_TIME is not set | 994 | CONFIG_FEATURE_PS_TIME=y |
995 | # CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set | 995 | # CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set |
996 | # CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set | 996 | # CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set |
997 | # CONFIG_PSTREE is not set | 997 | # CONFIG_PSTREE is not set |
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index 286846f95..c474c13ee 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -991,7 +991,7 @@ CONFIG_FEATURE_PIDOF_OMIT=y | |||
991 | CONFIG_PS=y | 991 | CONFIG_PS=y |
992 | # CONFIG_FEATURE_PS_WIDE is not set | 992 | # CONFIG_FEATURE_PS_WIDE is not set |
993 | # CONFIG_FEATURE_PS_LONG is not set | 993 | # CONFIG_FEATURE_PS_LONG is not set |
994 | # CONFIG_FEATURE_PS_TIME is not set | 994 | CONFIG_FEATURE_PS_TIME=y |
995 | # CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set | 995 | # CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set |
996 | # CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set | 996 | # CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set |
997 | # CONFIG_PSTREE is not set | 997 | # CONFIG_PSTREE is not set |
diff --git a/include/mingw.h b/include/mingw.h index dd676bf2c..87abd077b 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -374,6 +374,10 @@ clock_t times(struct tms *buf); | |||
374 | 374 | ||
375 | #define _SC_CLK_TCK 2 | 375 | #define _SC_CLK_TCK 2 |
376 | 376 | ||
377 | #define TICKS_PER_SECOND 100 | ||
378 | #define MS_PER_TICK 10 | ||
379 | #define HNSEC_PER_TICK 100000 | ||
380 | |||
377 | IMPL(alarm,unsigned int,0,unsigned int seconds UNUSED_PARAM); | 381 | IMPL(alarm,unsigned int,0,unsigned int seconds UNUSED_PARAM); |
378 | IMPL(chown,int,0,const char *path UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM); | 382 | IMPL(chown,int,0,const char *path UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM); |
379 | NOIMPL(chroot,const char *root UNUSED_PARAM); | 383 | NOIMPL(chroot,const char *root UNUSED_PARAM); |
@@ -475,3 +479,6 @@ int has_exe_suffix(const char *p); | |||
475 | char *file_is_win32_executable(const char *p); | 479 | char *file_is_win32_executable(const char *p); |
476 | 480 | ||
477 | int err_win_to_posix(DWORD winerr); | 481 | int err_win_to_posix(DWORD winerr); |
482 | |||
483 | ULONGLONG CompatGetTickCount64(void); | ||
484 | #define GetTickCount64 CompatGetTickCount64 | ||
diff --git a/procps/ps.c b/procps/ps.c index a8541e6cf..de062fe8b 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -35,7 +35,6 @@ | |||
35 | //config: bool "Enable -o time and -o etime specifiers" | 35 | //config: bool "Enable -o time and -o etime specifiers" |
36 | //config: default y | 36 | //config: default y |
37 | //config: depends on (PS || MINIPS) && DESKTOP | 37 | //config: depends on (PS || MINIPS) && DESKTOP |
38 | //config: select PLATFORM_LINUX | ||
39 | //config: | 38 | //config: |
40 | //config:config FEATURE_PS_UNUSUAL_SYSTEMS | 39 | //config:config FEATURE_PS_UNUSUAL_SYSTEMS |
41 | //config: bool "Support Linux prior to 2.4.0 and non-ELF systems" | 40 | //config: bool "Support Linux prior to 2.4.0 and non-ELF systems" |
@@ -126,7 +125,7 @@ static unsigned long get_uptime(void) | |||
126 | if (sysinfo(&info) < 0) | 125 | if (sysinfo(&info) < 0) |
127 | return 0; | 126 | return 0; |
128 | return info.uptime; | 127 | return info.uptime; |
129 | #elif 1 | 128 | #elif !ENABLE_PLATFORM_MINGW32 |
130 | unsigned long uptime; | 129 | unsigned long uptime; |
131 | char buf[sizeof(uptime)*3 + 2]; | 130 | char buf[sizeof(uptime)*3 + 2]; |
132 | /* /proc/uptime is "UPTIME_SEC.NN IDLE_SEC.NN\n" | 131 | /* /proc/uptime is "UPTIME_SEC.NN IDLE_SEC.NN\n" |
@@ -137,6 +136,8 @@ static unsigned long get_uptime(void) | |||
137 | buf[sizeof(buf)-1] = '\0'; | 136 | buf[sizeof(buf)-1] = '\0'; |
138 | sscanf(buf, "%lu", &uptime); | 137 | sscanf(buf, "%lu", &uptime); |
139 | return uptime; | 138 | return uptime; |
139 | #elif ENABLE_PLATFORM_MINGW32 | ||
140 | return GetTickCount64()/1000; | ||
140 | #else | 141 | #else |
141 | struct timespec ts; | 142 | struct timespec ts; |
142 | if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) | 143 | if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) |
@@ -556,7 +557,7 @@ static void format_process(const procps_status_t *ps) | |||
556 | # define SELINUX_O_PREFIX "label," | 557 | # define SELINUX_O_PREFIX "label," |
557 | # define DEFAULT_O_STR (SELINUX_O_PREFIX "pid,user" IF_FEATURE_PS_TIME(",time") ",args") | 558 | # define DEFAULT_O_STR (SELINUX_O_PREFIX "pid,user" IF_FEATURE_PS_TIME(",time") ",args") |
558 | #elif ENABLE_PLATFORM_MINGW32 | 559 | #elif ENABLE_PLATFORM_MINGW32 |
559 | # define DEFAULT_O_STR ("pid,ppid,comm") | 560 | # define DEFAULT_O_STR ("pid,ppid" IF_FEATURE_PS_TIME(",time,etime") ",comm") |
560 | #else | 561 | #else |
561 | # define DEFAULT_O_STR ("pid,user" IF_FEATURE_PS_TIME(",time") ",args") | 562 | # define DEFAULT_O_STR ("pid,user" IF_FEATURE_PS_TIME(",time") ",args") |
562 | #endif | 563 | #endif |
diff --git a/win32/lazyload.h b/win32/lazyload.h new file mode 100644 index 000000000..9d1a05550 --- /dev/null +++ b/win32/lazyload.h | |||
@@ -0,0 +1,43 @@ | |||
1 | #ifndef LAZYLOAD_H | ||
2 | #define LAZYLOAD_H | ||
3 | |||
4 | /* simplify loading of DLL functions */ | ||
5 | |||
6 | struct proc_addr { | ||
7 | const char *const dll; | ||
8 | const char *const function; | ||
9 | FARPROC pfunction; | ||
10 | unsigned initialized : 1; | ||
11 | }; | ||
12 | |||
13 | /* Declares a function to be loaded dynamically from a DLL. */ | ||
14 | #define DECLARE_PROC_ADDR(dll, rettype, function, ...) \ | ||
15 | static struct proc_addr proc_addr_##function = \ | ||
16 | { #dll, #function, NULL, 0 }; \ | ||
17 | static rettype (WINAPI *function)(__VA_ARGS__) | ||
18 | |||
19 | /* | ||
20 | * Loads a function from a DLL (once-only). | ||
21 | * Returns non-NULL function pointer on success. | ||
22 | * Returns NULL + errno == ENOSYS on failure. | ||
23 | */ | ||
24 | #define INIT_PROC_ADDR(function) (function = get_proc_addr(&proc_addr_##function)) | ||
25 | |||
26 | static inline void *get_proc_addr(struct proc_addr *proc) | ||
27 | { | ||
28 | /* only do this once */ | ||
29 | if (!proc->initialized) { | ||
30 | HANDLE hnd; | ||
31 | proc->initialized = 1; | ||
32 | hnd = LoadLibraryExA(proc->dll, NULL, | ||
33 | LOAD_LIBRARY_SEARCH_SYSTEM32); | ||
34 | if (hnd) | ||
35 | proc->pfunction = GetProcAddress(hnd, proc->function); | ||
36 | } | ||
37 | /* set ENOSYS if DLL or function was not found */ | ||
38 | if (!proc->pfunction) | ||
39 | errno = ENOSYS; | ||
40 | return proc->pfunction; | ||
41 | } | ||
42 | |||
43 | #endif | ||
diff --git a/win32/mingw.c b/win32/mingw.c index 7f37eadda..afcb6c6d2 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -707,7 +707,7 @@ int getlogin_r(char *buf, size_t len) | |||
707 | long sysconf(int name) | 707 | long sysconf(int name) |
708 | { | 708 | { |
709 | if ( name == _SC_CLK_TCK ) { | 709 | if ( name == _SC_CLK_TCK ) { |
710 | return 100; | 710 | return TICKS_PER_SECOND; |
711 | } | 711 | } |
712 | errno = EINVAL; | 712 | errno = EINVAL; |
713 | return -1; | 713 | return -1; |
@@ -1064,3 +1064,19 @@ off_t mingw_lseek(int fd, off_t offset, int whence) | |||
1064 | } | 1064 | } |
1065 | return _lseeki64(fd, offset, whence); | 1065 | return _lseeki64(fd, offset, whence); |
1066 | } | 1066 | } |
1067 | |||
1068 | #if ENABLE_FEATURE_PS_TIME || ENABLE_FEATURE_PS_LONG | ||
1069 | #undef GetTickCount64 | ||
1070 | #include "lazyload.h" | ||
1071 | |||
1072 | ULONGLONG CompatGetTickCount64(void) | ||
1073 | { | ||
1074 | DECLARE_PROC_ADDR(kernel32.dll, ULONGLONG, GetTickCount64, void); | ||
1075 | |||
1076 | if (!INIT_PROC_ADDR(GetTickCount64)) { | ||
1077 | return (ULONGLONG)GetTickCount(); | ||
1078 | } | ||
1079 | |||
1080 | return GetTickCount64(); | ||
1081 | } | ||
1082 | #endif | ||
diff --git a/win32/process.c b/win32/process.c index c0ff78105..f88a4898c 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -334,8 +334,18 @@ mingw_execv(const char *cmd, char *const *argv) | |||
334 | return mingw_execve(cmd, argv, environ); | 334 | return mingw_execve(cmd, argv, environ); |
335 | } | 335 | } |
336 | 336 | ||
337 | static inline long long filetime_to_ticks(const FILETIME *ft) | ||
338 | { | ||
339 | return (((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime)/ | ||
340 | HNSEC_PER_TICK; | ||
341 | } | ||
342 | |||
337 | /* POSIX version in libbb/procps.c */ | 343 | /* POSIX version in libbb/procps.c */ |
338 | procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags UNUSED_PARAM) | 344 | procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags |
345 | #if !ENABLE_FEATURE_PS_TIME && !ENABLE_FEATURE_PS_LONG | ||
346 | UNUSED_PARAM | ||
347 | #endif | ||
348 | ) | ||
339 | { | 349 | { |
340 | PROCESSENTRY32 pe; | 350 | PROCESSENTRY32 pe; |
341 | 351 | ||
@@ -361,6 +371,41 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags UNUSED_PAR | |||
361 | } | 371 | } |
362 | } | 372 | } |
363 | 373 | ||
374 | #if ENABLE_FEATURE_PS_TIME || ENABLE_FEATURE_PS_LONG | ||
375 | if (flags & (PSSCAN_STIME|PSSCAN_UTIME|PSSCAN_START_TIME)) { | ||
376 | HANDLE proc; | ||
377 | FILETIME crTime, exTime, keTime, usTime; | ||
378 | |||
379 | if ((proc=OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, | ||
380 | FALSE, pe.th32ProcessID))) { | ||
381 | if (GetProcessTimes(proc, &crTime, &exTime, &keTime, &usTime)) { | ||
382 | /* times in ticks since 1 January 1601 */ | ||
383 | static long long boot_time = 0; | ||
384 | long long start_time; | ||
385 | |||
386 | if (boot_time == 0) { | ||
387 | long long ticks_since_boot; | ||
388 | FILETIME now; | ||
389 | |||
390 | ticks_since_boot = GetTickCount64()/MS_PER_TICK; | ||
391 | GetSystemTimeAsFileTime(&now); | ||
392 | boot_time = filetime_to_ticks(&now) - ticks_since_boot; | ||
393 | } | ||
394 | |||
395 | start_time = filetime_to_ticks(&crTime); | ||
396 | sp->start_time = (unsigned long)(start_time - boot_time); | ||
397 | |||
398 | sp->stime = (unsigned long)filetime_to_ticks(&keTime); | ||
399 | sp->utime = (unsigned long)filetime_to_ticks(&usTime); | ||
400 | } | ||
401 | else { | ||
402 | sp->start_time = sp->stime = sp->utime = 0; | ||
403 | } | ||
404 | CloseHandle(proc); | ||
405 | } | ||
406 | } | ||
407 | #endif | ||
408 | |||
364 | sp->pid = pe.th32ProcessID; | 409 | sp->pid = pe.th32ProcessID; |
365 | sp->ppid = pe.th32ParentProcessID; | 410 | sp->ppid = pe.th32ParentProcessID; |
366 | safe_strncpy(sp->comm, pe.szExeFile, COMM_LEN); | 411 | safe_strncpy(sp->comm, pe.szExeFile, COMM_LEN); |