From owner-freebsd-hackers@FreeBSD.ORG Sat Nov 13 23:03:30 2010 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 65FD81065672 for ; Sat, 13 Nov 2010 23:03:30 +0000 (UTC) (envelope-from dteske@vicor.com) Received: from postoffice.vicor.com (postoffice.vicor.com [69.26.56.53]) by mx1.freebsd.org (Postfix) with ESMTP id 121168FC14 for ; Sat, 13 Nov 2010 23:03:29 +0000 (UTC) Received: from [71.202.142.31] (port=55485 helo=[192.168.1.93]) by postoffice.vicor.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.71) (envelope-from ) id 1PHP7x-0002Bf-9c; Sat, 13 Nov 2010 15:03:29 -0800 Mime-Version: 1.0 (Apple Message framework v1081) From: Devin Teske In-Reply-To: Date: Sat, 13 Nov 2010 15:03:18 -0800 Message-Id: <2CCA101F-22FA-4CE2-8F4C-117824CEA104@vicor.com> References: <1289506363.30235.113.camel@localhost.localdomain> To: "Carlos A. M. dos Santos" X-Mailer: Apple Mail (2.1081) X-Scan-Signature: a8ccddc25a85d58455f56c80af70d292 X-Scan-Host: postoffice.vicor.com Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: FreeBSD Hackers Subject: Re: Spinner Function for Shell Scripts X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Nov 2010 23:03:30 -0000 On Nov 13, 2010, at 1:19 PM, Carlos A. M. dos Santos wrote: > On Thu, Nov 11, 2010 at 6:12 PM, Devin Teske wrote: >> Hi fellow hackers... I come with baring gifts! >>=20 >> So, just as the subject-line says, ... here's an efficient and robust >> spinner function compatible with many shells. >> DONE=3D$( /bin/sh -c 'read -t 0 DONE; echo = $DONE' ) >=20 > Is this expected to be portable to other operating systems? The dash > shell, used as /bin/bash in Ubuntu, does not acept the "-t" argument > to the read builtin command. Using /bin/bash solves the problem. I was shooting for bourne-shell, but later realized that bash's read = statement functions fundamentally different than bourne's (hence the = direct invocation of /bin/sh). On FreeBSD: $ echo 'Hello' | /bin/sh -c 'read -t 0 DONE; echo $DONE' Hello $ echo 'Hello' | /bin/bash -c 'read -t 0 DONE; echo $DONE' $ echo 'Hello' | /bin/bash -c 'read -t 1 DONE; echo $DONE' Hello $ /bin/bash -c 'read -t 0.5 DONE; echo $DONE' /bin/bash: line 0: read: 0.5: invalid timeout specification As you can see from the above, passing a timeout specification of zero = to bourne-shell has the desired effect... if the stdin file descriptor = has something to offer the read-statement, input will be read up-to the = ending newline. Whereas, you can see that bash's implementation returns = nothing from the read despite data being available. Naturally, one can = get the data into bash's read by using a timeout of one, but that would = be unacceptable to our spinner to rotate the spinner one-quarter spin = each second. Last, the potential work-around of using finer measurements = of time is not allowed. However, this shouldn't be considered a bug, given the following = description of the timeout option in bash's InfoTex manual: `-t TIMEOUT' Cause `read' to time out and return failure if a complete line of input is not read within TIMEOUT seconds. This option has no effect if `read' is not reading input from the terminal or a pipe. Now, compare that with the description from bourne-shell's man-page = (sh(1)): If the -t option is specified and the timeout elapses = before any input is supplied, the read command will return without = assigning any values. The timeout value may optionally be followed = by one of ``s'', ``m'' or ``h'' to explicitly specify seconds, = minutes or hours. If none is supplied, ``s'' is assumed. So, as you can see, bash will timeout if a full line is not received in = the duration specified as the timeout, while bourne-shell will timeout = only if no input is supplied for the same duration. For our purposes, we want bourne-shell's implementation, not bash's (at = least on FreeBSD). I also tested Mac OS X 10.6.1, FreeBSD-8.1, CentOS 4.7, RedHat = Enterprise Linux (RHEL) 4 Nahant Update 4 (U4), and also RHEL4U8. Here's the breakdown for the test of ``read -t 0 LINE; echo $LINE'': Mac OS X 10.6.1: sh: FAIL bash: FAIL RedHat Enterprise Linux (RHEL) 4 Update 4 (U4): sh: FAIL bash: FAIL RedHat Enterprise Linux (RHEL) 4 Update 8 (U8): sh: FAIL bash: FAIL CentOS 4.7: sh: FAIL bash: FAIL FreeBSD-4.8: sh: SUCCEED bash: FAIL FreeBSD-4.11: sh: SUCCEED bash: FAIL FreeBSD-8.1: sh: SUCCEED bash: FAIL This is not so surprising... On all of the above-tested Linux OSes, = /bin/sh is a symbolic link to bash(1). On Mac OS X, /bin/sh is simply a = bash binary (try /bin/sh --version). It's rather unfortunate that bourne-shell has what we need but is not = available on all operating systems since many OSes have started swapping = out bourne-shell for it's younger cousin. Does anyone else happen to know of a portable way to quickly check if = data is available on a given file descriptor? -- Cheers, Devin Teske -> CONTACT INFORMATION <- Business Solutions Consultant II FIS - fisglobal.com 510-735-5650 Mobile 510-621-2038 Office 510-621-2020 Office Fax 909-477-4578 Home/Fax devin.teske@fisglobal.com -> LEGAL DISCLAIMER <- This message contains confidential and proprietary information of the sender, and is intended only for the person(s) to whom it is addressed. Any use, distribution, copying or disclosure by any other person is strictly prohibited. If you have received this message in error, please notify the e-mail sender immediately, and delete the original message without making a copy. -> END TRANSMISSION <-