mirror of
				git://git.code.sf.net/p/cdesktopenv/code
				synced 2025-03-09 15:50:02 +00:00 
			
		
		
		
	Now that we have an iffe feature test for getrusage(3), introduced
in 70fc1da7, the millisecond-precision 'times' command from the
last version of ksh2020 can easily be backported.
src/cmd/ksh93/bltins/misc.c:
- Incorporate ksh2020 'times' command, with a couple of tweaks:
  * Use locale's radix point instead of '.'.
  * Pad seconds with initial zero if < 10.
src/cmd/ksh93/data/builtins.c:
- Update version date for 'times --man'.
src/cmd/ksh93/tests/builtins.sh:
- Update 'times' test for 3 digits after radix point.
			
			
This commit is contained in:
		
							parent
							
								
									c5820aabc9
								
							
						
					
					
						commit
						b1a4131123
					
				
					 4 changed files with 59 additions and 13 deletions
				
			
		
							
								
								
									
										3
									
								
								NEWS
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								NEWS
									
										
									
									
									
								
							| 
						 | 
					@ -7,6 +7,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fixed a bug that caused 'set -b' to have no effect.
 | 
					- Fixed a bug that caused 'set -b' to have no effect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Following the 'time' keyword, the 'times' builtin command now also
 | 
				
			||||||
 | 
					  supports millisecond precision.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2020-07-13:
 | 
					2020-07-13:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fixed a fork bomb that could occur when the vi editor was sent SIGTSTP
 | 
					- Fixed a fork bomb that could occur when the vi editor was sent SIGTSTP
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,13 @@
 | 
				
			||||||
#include	"jobs.h"
 | 
					#include	"jobs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include	<math.h>
 | 
					#include	<math.h>
 | 
				
			||||||
 | 
					#include	"FEATURE/locale"
 | 
				
			||||||
 | 
					#include	"FEATURE/time"
 | 
				
			||||||
 | 
					#if _lib_getrusage
 | 
				
			||||||
 | 
					#include	<sys/resource.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
#include	<times.h>
 | 
					#include	<times.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DOTMAX	MAXDEPTH	/* maximum level of . nesting */
 | 
					#define DOTMAX	MAXDEPTH	/* maximum level of . nesting */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -464,17 +470,57 @@ int    b_jobs(register int n,char *argv[],Shbltin_t *context)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * times command
 | 
					 * times command
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void print_times(clock_t uticks, clock_t sticks, Shbltin_t *context)
 | 
					static void	print_times(struct timeval utime, struct timeval stime)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int clk_tck = context->shp->gd->lim.clk_tck;
 | 
						int ut_min = utime.tv_sec / 60;
 | 
				
			||||||
	double utime = (double)uticks / clk_tck, stime = (double)sticks / clk_tck;
 | 
						int ut_sec = utime.tv_sec % 60;
 | 
				
			||||||
	sfprintf(sfstdout, "%dm%05.2fs %dm%05.2fs\n",
 | 
						int ut_ms = utime.tv_usec / 1000;
 | 
				
			||||||
		(int)floor(utime / 60), fmod(utime, 60),
 | 
						int st_min = stime.tv_sec / 60;
 | 
				
			||||||
		(int)floor(stime / 60), fmod(stime, 60));
 | 
						int st_sec = stime.tv_sec % 60;
 | 
				
			||||||
 | 
						int st_ms = stime.tv_usec / 1000;
 | 
				
			||||||
 | 
						char radix = GETDECIMAL(0);
 | 
				
			||||||
 | 
						sfprintf(sfstdout, "%dm%02d%c%03ds %dm%02d%c%03ds\n", ut_min, ut_sec, radix, ut_ms, st_min, st_sec, radix, st_ms);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#if _lib_getrusage
 | 
				
			||||||
 | 
					static void	print_cpu_times()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rusage usage;
 | 
				
			||||||
 | 
						/* Print the time (user & system) consumed by the shell. */
 | 
				
			||||||
 | 
						getrusage(RUSAGE_SELF, &usage);
 | 
				
			||||||
 | 
						print_times(usage.ru_utime, usage.ru_stime);
 | 
				
			||||||
 | 
						/* Print the time (user & system) consumed by the child processes of the shell. */
 | 
				
			||||||
 | 
						getrusage(RUSAGE_CHILDREN, &usage);
 | 
				
			||||||
 | 
						print_times(usage.ru_utime, usage.ru_stime);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else  /* _lib_getrusage */
 | 
				
			||||||
 | 
					static void	print_cpu_times()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct timeval utime, stime;
 | 
				
			||||||
 | 
						double dtime;
 | 
				
			||||||
 | 
						int clk_tck = shgd->lim.clk_tck;
 | 
				
			||||||
 | 
						struct tms cpu_times;
 | 
				
			||||||
 | 
						times(&cpu_times);
 | 
				
			||||||
 | 
						/* Print the time (user & system) consumed by the shell. */
 | 
				
			||||||
 | 
						dtime = (double)cpu_times.tms_utime / clk_tck;
 | 
				
			||||||
 | 
						utime.tv_sec = dtime / 60;
 | 
				
			||||||
 | 
						utime.tv_usec = 1000000 * (dtime - utime.tv_sec);
 | 
				
			||||||
 | 
						dtime = (double)cpu_times.tms_stime / clk_tck;
 | 
				
			||||||
 | 
						stime.tv_sec = dtime / 60;
 | 
				
			||||||
 | 
						stime.tv_usec = 1000000 * (dtime - utime.tv_sec);
 | 
				
			||||||
 | 
						print_times(utime, stime);
 | 
				
			||||||
 | 
						/* Print the time (user & system) consumed by the child processes of the shell. */
 | 
				
			||||||
 | 
						dtime = (double)cpu_times.tms_cutime / clk_tck;
 | 
				
			||||||
 | 
						utime.tv_sec = dtime / 60;
 | 
				
			||||||
 | 
						utime.tv_usec = 1000000 * (dtime - utime.tv_sec);
 | 
				
			||||||
 | 
						dtime = (double)cpu_times.tms_cstime / clk_tck;
 | 
				
			||||||
 | 
						stime.tv_sec = dtime / 60;
 | 
				
			||||||
 | 
						stime.tv_usec = 1000000 * (dtime - utime.tv_sec);
 | 
				
			||||||
 | 
						print_times(utime, stime);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif  /* _lib_getrusage */
 | 
				
			||||||
int	b_times(int argc, char *argv[], Shbltin_t *context)
 | 
					int	b_times(int argc, char *argv[], Shbltin_t *context)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tms cpu_times;
 | 
						NOT_USED(context);
 | 
				
			||||||
	/* No options or operands are supported, except --man, etc. */
 | 
						/* No options or operands are supported, except --man, etc. */
 | 
				
			||||||
	if (argc = optget(argv, sh_opttimes)) switch (argc)
 | 
						if (argc = optget(argv, sh_opttimes)) switch (argc)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -488,10 +534,7 @@ int	b_times(int argc, char *argv[], Shbltin_t *context)
 | 
				
			||||||
	if (argv[opt_info.index])
 | 
						if (argv[opt_info.index])
 | 
				
			||||||
		errormsg(SH_DICT, ERROR_exit(2), e_toomanyops);
 | 
							errormsg(SH_DICT, ERROR_exit(2), e_toomanyops);
 | 
				
			||||||
	/* Get & print the times */
 | 
						/* Get & print the times */
 | 
				
			||||||
	if (times(&cpu_times) == (clock_t)-1)
 | 
						print_cpu_times();
 | 
				
			||||||
		errormsg(SH_DICT, ERROR_exit(1), "times(3) failed: %s", strerror(errno));
 | 
					 | 
				
			||||||
	print_times(cpu_times.tms_utime, cpu_times.tms_stime, context);
 | 
					 | 
				
			||||||
	print_times(cpu_times.tms_cutime, cpu_times.tms_cstime, context);
 | 
					 | 
				
			||||||
	return(0);
 | 
						return(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1906,7 +1906,7 @@ USAGE_LICENSE
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char sh_opttimes[] =
 | 
					const char sh_opttimes[] =
 | 
				
			||||||
"[-1c?@(#)$Id: times (ksh93) 2020-06-24 $\n]"
 | 
					"[-1c?@(#)$Id: times (ksh93) 2020-07-14 $\n]"
 | 
				
			||||||
"[+NAME?times - display CPU usage by the shell and child processes]"
 | 
					"[+NAME?times - display CPU usage by the shell and child processes]"
 | 
				
			||||||
"[+DESCRIPTION?\btimes\b displays the accumulated user and system CPU times, "
 | 
					"[+DESCRIPTION?\btimes\b displays the accumulated user and system CPU times, "
 | 
				
			||||||
"one line with the times used by the shell and another with those used by "
 | 
					"one line with the times used by the shell and another with those used by "
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -700,7 +700,7 @@ fi
 | 
				
			||||||
# ======
 | 
					# ======
 | 
				
			||||||
# 'times' builtin
 | 
					# 'times' builtin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
expect=$'0m00.0[0-9]s 0m00.0[0-9]s\n0m00.00s 0m00.00s'
 | 
					expect=$'0m00.0[0-9][0-9]s 0m00.0[0-9][0-9]s\n0m00.000s 0m00.000s'
 | 
				
			||||||
actual=$("$SHELL" -c times)
 | 
					actual=$("$SHELL" -c times)
 | 
				
			||||||
[[ $actual == $expect ]] || err_exit "times output: expected $(printf %q "$expect"), got $(printf %q "$actual"))"
 | 
					[[ $actual == $expect ]] || err_exit "times output: expected $(printf %q "$expect"), got $(printf %q "$actual"))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue