POSIX compliance...


 
Thread Tools Search this Thread
Operating Systems OS X (Apple) POSIX compliance...
# 1  
Old 07-05-2016
POSIX compliance...

Thanks to all you guys about posix compliance I have learnt an enormous amount over the last few days.
I have written a program that is an Egg Timer with simple animation.
I now realise how sophisticated 'bash' is compared to full posix compliance.
The code below has passed all of the tests from ShellCheck and boy have I found out a lot from it.
So the only way for me to learn was to create this program...
Enjoy...
(No doubt the big guns will find a better way... ;o) )
Code:
#!/bin/sh
# Egg_Timer.sh
# Fully POSIX compliant.
# Tested on OSX 10.7.5, OSX 10.11.3, Ubuntu64 and CygWin64 on Windows 8.1.
# It has fully passed CheckShell's tests. Tuesday July 5th, 2016.
# Public Domain, 2016, B.Walker, G0LCU.

mins=3
secs=0
fsecs=1.00000
keyboard="?"
width=12
horiz=36
vert=3
spaces='              '
stars='**************'
char=0
platform=$( uname )

# Generate the sinewave beep.
if [ ! -e "/tmp/beep.wav" ]
then
	> /tmp/beep.wav
	printf "\122\111\106\106\144\037\000\000\127\101\126\105\146\155\164\040\020\000\000\000\001\000\001\000\100\037\000\000\100\037\000\000\001\000\010\000\144\141\164\141\100\037\000\000" >> /tmp/beep.wav
	while [ $char -le 999 ]
	do
		printf "\200\046\000\046\177\331\377\331" >> /tmp/beep.wav
		char=$(( char + 1 ))
	done
fi

clrscn()
{
	# A default CygWin and CygWin64 install does not have 'clear' nor 'tput'!
	printf "\033c\033[0m\033[2J\033[H"
}

display()
{
	clrscn
	echo '	  At a glance Egg Timer, Public Domain, 2016, B.Walker, G0LCU.
				   ____________  
				 / ************ \ 
				||**************|| 
				 \**************/ 
				  \************/ 
				   \**********/ 
				    \********/ 
				     \******/ 
				      \****/ 
				       \**/ 
				        || 
				       /..\ 
				      / .. \ 
				     /  ..  \ 
				    /   ..   \ 
				   /    ..    \ 
				  /     ..     \ 
				 /      ..      \ 
				||      ..      || 
				 \      **      / 
__________________________________==============________________________________'
	echo "			      Time set to $secs seconds."
}

set_time()
{
	clrscn
	echo ''
	echo '		Enter the timer time in minutes first and seconds next.'
	echo ''
	printf 'Enter the number of minutes:- '
	read -r mins
	echo ''
	printf 'Enter the number of seconds:- '
	read -r secs
	echo ''
	printf "Timer set to %s? minutes and %s? seconds, are these correct? (Y/N):- " "$mins" "$secs"
	read -r keyboard
	if [ "$keyboard" = "N" ] || [ "$keyboard" = "n" ]
	then
		set_time
	fi

	# Check for typos and other errors.
	case $mins in
		''|*[!0-9]*) mins=3 ;;
	esac
	case $secs in
		''|*[!0-9]*) secs=0 ;;
	esac
	if [ $mins -gt 59 ] || [ $mins -lt 0 ]
	then
		mins=59
	fi
	if [ $secs -gt 59 ] || [ $secs -lt 0 ]
	then
		secs=59
	fi
	secs=$(( ( mins * 60 ) + secs ))
	if [ $secs -lt 15 ]
	then
		secs=15
	fi
	# A default CygWin or CygWin64 install does not have 'bc' nor 'dc'.
	fsecs=$( awk -v fp=$secs 'BEGIN { print ( fp / 17 ); }' )
}

# Main loop.
while true
do
	set_time
	horiz=36
	keyboard="?"
	width=12
	spaces='              '
	stars='**************'
	display
	sleep "$fsecs"
	printf "\033[3;36f      \033[24;1f"
	for vert in 3 4 5
	do
		printf "\033[%u;35f%s\033[24;1f" "$(( 24 - vert ))" "$stars"
		printf "\033[%u;35f%s\033[24;1f" "$vert" "$spaces"
		sleep "$fsecs"
		printf "\033[%u;41f**\033[24;1f" "$(( 23 - vert ))"
		sleep "$fsecs"
	done
	for vert in 6 7 8 9 10
	do
		char=$( awk -v star="$stars" -v wide="$width" 'BEGIN { print substr(star,1,wide); }' )
		printf "\033[%u;%uf%s\033[24;1f" "$(( 24 - vert ))" "$horiz" "$char"
		char=$( awk -v space="$spaces" -v wide="$width" 'BEGIN { print substr(space,1,wide); }' )
		printf "\033[%u;%uf%s\033[24;1f" "$vert" "$horiz" "$char"
		sleep "$fsecs"
		printf "\033[%u;41f**\033[24;1f" "$(( 23 - vert ))"
		sleep "$fsecs"
		horiz=$(( horiz + 1 ))
		width=$(( width - 2 ))
	done
	printf "\033[11;%uf  \033[24;1f" "$horiz"
	for char in 1 2 3
	do
		if [ "$platform" = "Darwin" ]
		then
			afplay /tmp/beep.wav > /dev/null 2>&1
		else
			aplay /tmp/beep.wav > /dev/null 2>&1
		fi
		if [ "$( awk -v name="$platform" 'BEGIN { print substr(name,1,6); } ')" = "CYGWIN" ]
		then
			cat /tmp/beep.wav > /dev/dsp
		fi
	done
	printf 'Run again? (Y/N):- '
	read -r keyboard
	if [ "$keyboard" = "N" ] || [ "$keyboard" = "n" ]
	then
		break
	fi
done
clrscn
exit 0
# Egg_Timer.sh end.

# 2  
Old 07-06-2016
Hi Barry,

That looks quite neat and Posixy!

Some comments and ideas:
  • The sleep command is not used in a POSIX compliant ways, since it gets fed a float here, and in POSIX it can only handle integers. An alternative is maybe to fill the hourglass more or less from the start, depending on the number of minutes / seconds, and compensate the rest with the first sleep command.
  • Instead of using awk to cut the first 6 characters you could use "${platform%"${platform#??????}"}" or better yet, replace the if statements with one case statement and use it pattern matching capability CYGWIN*), so you do not need to cut the platform string.
  • The awk command substitutions in the 2nd for loop take time and will skew the time slightly. An alternative is to use parameter expansions or predefine the strings so that it does not add as much to the time used by the sleep commands..
  • Perhaps you could have a seconds countdown instead of the static number.
  • If more time is entered than what the hourglass can handle, graphically turn the hourglass (nice scripting challenge?)
This User Gave Thanks to Scrutinizer For This Post:
# 3  
Old 07-06-2016
Apologies for any typos...
Quote:
Originally Posted by Scrutinizer
Hi Barry,

That looks quite neat and Posixy!

Some comments and ideas:
  • The sleep command is not used in a POSIX compliant ways, since it gets fed a float here, and in POSIX it can only handle integers. An alternative is maybe to fill the hourglass more or less from the start, depending on the number of minutes / seconds, and compensate the rest with the first sleep command.
  • Instead of using awk to cut the first 6 characters you could use "${platform%"${platform#??????}"}" or better yet, replace the if statements with one case statement and use it pattern matching capability CYGWIN*), so you do not need to cut the platform string.
  • The awk command substitutions in the 2nd for loop take time and will skew the time slightly. An alternative is to use parameter expansions or predefine the strings so that it does not add as much to the time used by the sleep commands..
  • Perhaps you could have a seconds countdown instead of the static number.
  • If more time is entered than what the hourglass can handle, graphically turn the hourglass (nice scripting challenge?)
Thank you for these comments. I was half expecting to be slated... ;oD

I did check the auxiliary programs sleep and awk but could find nothing definite to tell me what was the current POSIX position for these.

I had lines similar to these:-
Code:
#!/bin/sh
text="1234567890"
char=$( cut -c2-6 <<< "$text" )
printf "%s" "${text:1:5}"
echo "$char"

Code:
$ shellcheck myscript
 
Line 3:
char=$( cut -c2-6 <<< "$text" )
                      ^-- SC2039: In POSIX sh, here-strings are undefined.
 
Line 4:
printf "%s" "${text:1:5}"
             ^-- SC2039: In POSIX sh, string indexing is undefined.

$ _

These really threw me and constant searching gave me the results inside the main code.
I could not find your "${platform%"${platform#??????}"}" anywhere, perhaps it was my search phrases but I spent hours trying to find non-time consuming methods without much success. Many thanks for those snippets.
I never even thought about using pettern matching, maybe because being an amateur I think differently to pros.

I was giong to use the "afplay", "aplay" and "/dev/dsp" as timers, (I will let you think about that one ;o) ), but decided against it as these are platform specific and would require some serious experimentation.

However I was aware of timings but that was not too important to me as learning POSIX requirements was; and guys like you supplying info helps others, (and judging by the posts on here, possibly tens of thousands of them), to steer through this quagmire too.

Again thanks, makes me feel good... ;o)

EDIT:
I forgot to add:- The rotating hourglass idea using ASCII - OUCH, but as you say a real challenge to draw at 45 degrees per movement... ;oO

Last edited by wisecracker; 07-06-2016 at 06:21 AM.. Reason: Rotating hourglass.
# 4  
Old 07-07-2016
Hi Barry, you are welcome of course.

One addition:
The awk command substitutions could be replaced by printf statements and integrated in the next printf statement, for example the first one could be:
Code:
printf "\033[%u;%.${width}s\033[24;1f" "$(( 24 - vert ))" "$horiz" "$stars"

The dot "." in the %s format specifier marks the precision of the string.

--
With regards to the sleep command:

The POSIX specification says:
Quote:
OPERANDS

The following operand shall be supported:

time
A non-negative decimal integer specifying the number of seconds for which to suspend execution.
sleep: Operands

And the OSX man sleep(1)
Quote:
IMPLEMENTATION NOTES
[..]
The sleep command will accept and honor a non-integer number of specified seconds
(with a `.' character as a decimal point). This is a non-portable extension, and its
use will nearly guarantee that a shell script will not execute properly on another
system.
https://www.unix.com/man-page/osx/1/sleep/

and GNU coreutils sleep:
Quote:
SYNOPSIS
sleep NUMBER[SUFFIX]...
sleep OPTION

DESCRIPTION
Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes,
'h' for hours or 'd' for days. Unlike most implementations that require NUMBER be an
integer, here NUMBER may be an arbitrary floating point number. Given two or more argu-
ments, pause for the amount of time specified by the sum of their values.
https://www.unix.com/man-page/centos/1/sleep/

Last edited by Scrutinizer; 07-07-2016 at 04:07 AM..
This User Gave Thanks to Scrutinizer For This Post:
# 5  
Old 07-07-2016
Hi Scrutinizer...
Many thanks for your post I will try your latest method this evening.

In the meantime......

I have an idea for a floating point sleep replacement using sleep.
Apart from the pseudo-code initialise something; while test something; do something_else; increment something; done ,
is there a POSIX equivalent to the BASIC form of 'FOR' loop without using seq :-
Code:
FOR n = number1 TO number2
[do something......]
NEXT

Again I have not found anything on the Interwebs.
Putting 'number1 TO number2' as a list works for small numbers say '1 2 3 4 5 6 7 8 9 10' but just imagine if that was '1 to 1000'.

It amazes me that this absolutely minmal use of posix 'for' loop is not catered for.
As I have written above I could use a 'while' loop which could inculde a pseud-STEP subcommand but this will need an initialisation line per call, easy yes, but a PITA.
It must be the way I search... ;o/

TIA.
# 6  
Old 07-07-2016
Some shells (such as bash and 1993 or later versions of ksh) provide:
Code:
for((n=1; n<=100; n++))
do	echo "process n=$n"
done

but this is an extension that is not yet specified by the standards. As you said, standard ways to do the same thing require an initialization step before the loop, such as in:
Code:
n=1
while [ $n -le 100 ]
do	echo "process n=$n"
	n=$((n + 1))
done

and in:
Code:
n=0
while [ $((++n <= 100)) -eq 1 ]
do	echo "process n=$n"
done

Note: As noted by Scrutinizer in post #8, the POSIX standards do not require $((++n)) to work. (It works with a recent bash and with a 1993 or later version of ksh, but is an extension to the requirements specified by the standards.)
Code:
n=0
while [ $(((n += 1) <= 100)) -eq 1 ]
do	echo "process n=$n"
done

should work in an POSIX-conforming shell.

Last edited by Don Cragun; 07-10-2016 at 04:56 PM.. Reason: Add note.
This User Gave Thanks to Don Cragun For This Post:
# 7  
Old 07-07-2016
Well I have been experimenting with sleep <secs> to give me a smaller time accurate to about + or - 5mS on this MacBook Pro, OSX 10.7.5.

It would be good enough for the Egg_Timer.sh and passes the ShellCheck test.

It is fully posix compliant with SLEEPs unity seconds timer only.

Boy am I gonna get some flak over this one, (yes I bend the rules a little)... ;o)
Code:
#!/bin/sh
# delay.sh <secs> <millisecs[0-999]>
secs="$1"
millisecs=$( awk -v mS="$2" -v correction=0.94 ' BEGIN { print (( mS / 2 ) * correction ); } ' )
millisecs="${millisecs%.*}"

# Accuracy on my MBP OSX 10.7.5 + or - 5mS of FSD.
mS()
{
	loop=0
	while [ "$loop" -le "$millisecs" ]
	do
		sleep 0
		wait
		loop=$(( loop + 1 ))
	done
}
# Test the mS function only.
time mS
sleep "$secs"

As I quoted in a previous post I could create a resonably accurate timer using 'afplay', 'aplay' or '/dev/dsp'. I might use afplay and make it Apple dedicated...

Thanks Don for the info...

I await the flak... ;o)
Login or Register to Ask a Question

Previous Thread | Next Thread

5 More Discussions You Might Find Interesting

1. HP-UX

Password compliance setting

I need to set password compliance for some servers in my company. However, the requirements are that we need to set different password policies for 3 different user groups within the company. These are : System Users: i.e root, etc Batch/Application Users: oracle, bscs, etc Standard User:... (0 Replies)
Discussion started by: anaigini45
0 Replies

2. Red Hat

Looking for PCI Compliance tool for Redhat Lix.

Hi i am in new to Linux world . I have been assigned to a project to find out a tool that will fulfill the PCI compliance for Linux servers for Audit process. anyone have any recommendation on that. Do Rad hat have any native application or plug-ins which we can use for that. (1 Reply)
Discussion started by: sahasuman
1 Replies

3. Cybersecurity

PCI DSS Compliance : Insecure Communication Has Been Detected

From the nessus scanner tool report i got below vulnerability PCI DSS Compliance : Insecure Communication Has Been Detected http://www.tenable.com/plugins/index.php?view=single&id=56208 As per the description given in above link - I am not able to understand How to find insecure port... (2 Replies)
Discussion started by: saurabh84g
2 Replies

4. UNIX for Dummies Questions & Answers

man synopsis standard compliance

In different online sources, I found bits and pieces of information about those square and angular brackets and pipes. From what I have read, I can conclude it looks like this: 1. Options outside any brackets are mandatory 2. Options inside these < .. > are mandatory too 3. Options inside ... (4 Replies)
Discussion started by: vkleban
4 Replies

5. UNIX for Advanced & Expert Users

sudo & Sox compliance

Hello, I am trying to convince my boss to stop allowing our users to login as root (superuser). Currently our users login to our unix server with their own account, then as needed, they will do an su and put in the root password. This scares me, for a bunch of reasons. Mainly, one is that we... (1 Reply)
Discussion started by: rwallaceisg
1 Replies
Login or Register to Ask a Question