aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-09-01 17:50:39 +0100
committerRon Yorston <rmy@pobox.com>2017-09-01 18:00:01 +0100
commitdd9f552bb1fee66f3155bbbb81c677def861ada0 (patch)
tree21c7f1f333a2a58361c813311188b286ea803c9c
parentec3ecac715b299766c101be92caf8b7cffb2a8b5 (diff)
downloadbusybox-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_defconfig2
-rw-r--r--configs/mingw64_defconfig2
-rw-r--r--include/mingw.h7
-rw-r--r--procps/ps.c7
-rw-r--r--win32/lazyload.h43
-rw-r--r--win32/mingw.c18
-rw-r--r--win32/process.c47
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
991CONFIG_PS=y 991CONFIG_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 994CONFIG_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
991CONFIG_PS=y 991CONFIG_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 994CONFIG_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
377IMPL(alarm,unsigned int,0,unsigned int seconds UNUSED_PARAM); 381IMPL(alarm,unsigned int,0,unsigned int seconds UNUSED_PARAM);
378IMPL(chown,int,0,const char *path UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM); 382IMPL(chown,int,0,const char *path UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM);
379NOIMPL(chroot,const char *root UNUSED_PARAM); 383NOIMPL(chroot,const char *root UNUSED_PARAM);
@@ -475,3 +479,6 @@ int has_exe_suffix(const char *p);
475char *file_is_win32_executable(const char *p); 479char *file_is_win32_executable(const char *p);
476 480
477int err_win_to_posix(DWORD winerr); 481int err_win_to_posix(DWORD winerr);
482
483ULONGLONG 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
6struct 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
26static 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)
707long sysconf(int name) 707long 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
1072ULONGLONG 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
337static 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 */
338procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags UNUSED_PARAM) 344procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags
345#if !ENABLE_FEATURE_PS_TIME && !ENABLE_FEATURE_PS_LONG
346UNUSED_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);