Subject: kern/219: no subject (file transmission)
To: None <gnats-admin>
From: Bob Kemp <rsk@ecs.soton.ac.uk>
List: netbsd-bugs
Date: 04/09/1994 15:05:02
>Number:         219
>Category:       kern
>Synopsis:       /dev/speaker occasionally doesn't stop beeping
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    gnats-admin (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Apr  9 15:05:02 1994
>Originator:     Bob Kemp
>Organization:
	ECS Dept, Southampton Univ, UK
>Release:        -current 05Mar94
>Environment:
System: NetBSD allegory 0.9a ALLEGORY#0 i386


>Description:
	Once in a blue moon, echoing commands to /dev/speaker hangs
	the writing process and produces some very avant garde
	electronic music (probably original).  In other words, it
	just keeps whirring and twittering and beeping.  It's
	vaguely pleasant and better than some I've heard but on
	the one occasion I haven't rebooted after a couple of
	minutes, the machine hung about 5 mins later.

>How-To-Repeat:
	Tricky :-)

	Try putting

	00  *   *   *   *		/usr/local/bin/chimes hour
	15  *   *   *   *		/usr/local/bin/chimes quarter
	30  *   *   *   *		/usr/local/bin/chimes half
	45  *   *   *   *		/usr/local/bin/chimes quarter

	in your crontab file and

	#!/bin/sh
	Chime="$1"
	exec 1>/dev/speaker
	case "$Chime" in
	quarter)
		echo -n c5; sleep 1 ;; 
	half)
		echo -n c5; sleep 1; echo -n c5; ;; 
	hour)
		echo -n c9; sleep 1; echo -n c9; sleep 1; echo -n c3 ;;
	*)
		echo "Unrecognised argument: '$Chime'"
	esac
	exit 0

	as /usr/local/bin/chimes.

	Assuming this doesn't drive you mad first, you will eventually
	see what I mean.  Perhaps.

>Fix:
... that probably isn't a fix.
I don't know if the following _will_ fix it but they certainly
tidy the code.  My suspicion is that the 
	for (; slen--; cp++)
should have been
	for (; slen-- > 0; cp++)
It's certainly safer that way.  The rest of the changes make explicit
the implicit "slen" argument to GETNUM.

*** spkr.c.orig	Thu Feb 10 11:13:57 1994
--- spkr.c	Sat Apr  9 17:38:14 1994
***************
*** 220,225 ****
--- 220,228 ----
  	return(n);
  }
  
+ #define GETNUM(cp, v, slen)	for(v=0; isdigit(cp[1]) && slen > 0; ) \
+ 					{v = v * 10 + (*++cp - '0'); slen--;}
+ 
  static void playstring(cp, slen)
  /* interpret and play an item from a notation string */
  char	*cp;
***************
*** 227,235 ****
  {
      int		pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
  
! #define GETNUM(cp, v)	for(v=0; isdigit(cp[1]) && slen > 0; ) \
! 				{v = v * 10 + (*++cp - '0'); slen--;}
!     for (; slen--; cp++)
      {
  	int		sustain, timeval, tempo;
  	register char	c = toupper(*cp);
--- 230,236 ----
  {
      int		pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
  
!     for (; slen-- > 0; cp++)
      {
  	int		sustain, timeval, tempo;
  	register char	c = toupper(*cp);
***************
*** 282,288 ****
  	    lastpitch = pitch;
  
  	    /* ...which may in turn be followed by an override time value */
! 	    GETNUM(cp, timeval);
  	    if (timeval <= 0 || timeval > MIN_VALUE)
  		timeval = value;
  
--- 283,289 ----
  	    lastpitch = pitch;
  
  	    /* ...which may in turn be followed by an override time value */
! 	    GETNUM(cp, timeval, slen);
  	    if (timeval <= 0 || timeval > MIN_VALUE)
  		timeval = value;
  
***************
*** 312,318 ****
  	    }
  	    else
  	    {
! 		GETNUM(cp, octave);
  		if (octave >= sizeof(pitchtab) / OCTAVE_NOTES)
  		    octave = DFLT_OCTAVE;
  		octprefix = TRUE;
--- 313,319 ----
  	    }
  	    else
  	    {
! 		GETNUM(cp, octave, slen);
  		if (octave >= sizeof(pitchtab) / OCTAVE_NOTES)
  		    octave = DFLT_OCTAVE;
  		octprefix = TRUE;
***************
*** 332,338 ****
  	    break;
  
  	case 'N':
! 	    GETNUM(cp, pitch);
  	    for (sustain = 0; cp[1] == '.'; cp++)
  	    {
  		slen--;
--- 333,339 ----
  	    break;
  
  	case 'N':
! 	    GETNUM(cp, pitch, slen);
  	    for (sustain = 0; cp[1] == '.'; cp++)
  	    {
  		slen--;
***************
*** 342,348 ****
  	    break;
  
  	case 'L':
! 	    GETNUM(cp, value);
  	    if (value <= 0 || value > MIN_VALUE)
  		value = DFLT_VALUE;
  	    break;
--- 343,349 ----
  	    break;
  
  	case 'L':
! 	    GETNUM(cp, value, slen);
  	    if (value <= 0 || value > MIN_VALUE)
  		value = DFLT_VALUE;
  	    break;
***************
*** 350,356 ****
  	case 'P':
  	case '~':
  	    /* this may be followed by an override time value */
! 	    GETNUM(cp, timeval);
  	    if (timeval <= 0 || timeval > MIN_VALUE)
  		timeval = value;
  	    for (sustain = 0; cp[1] == '.'; cp++)
--- 351,357 ----
  	case 'P':
  	case '~':
  	    /* this may be followed by an override time value */
! 	    GETNUM(cp, timeval, slen);
  	    if (timeval <= 0 || timeval > MIN_VALUE)
  		timeval = value;
  	    for (sustain = 0; cp[1] == '.'; cp++)
***************
*** 362,368 ****
  	    break;
  
  	case 'T':
! 	    GETNUM(cp, tempo);
  	    if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
  		tempo = DFLT_TEMPO;
  	    whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
--- 363,369 ----
  	    break;
  
  	case 'T':
! 	    GETNUM(cp, tempo, slen);
  	    if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
  		tempo = DFLT_TEMPO;
  	    whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;


>Audit-Trail:
>Unformatted:

------------------------------------------------------------------------------