[gnu.bash.bug] question about nojobs.c, bash-1.04

goer@sophist.uucp (Richard Goerwitz) (02/10/90)

Silly question?

/* from jobs.h */

union wait {
  struct {                           /* clever way of getting at
    unsigned char low;                * wait's high and low 
    unsigned char high;               * status bytes
  }                                   * /
  bytes;
  short word;
};

#define WSTOPPED 0177
#define w_status word
#define w_termsig bytes.low & 0x7f    /* mask out eighth bit */
#define w_stopsig bytes.high
#define w_retcode bytes.high


/* from nojobs.c, line 163 and following: */

  while ((got_pid = wait (&status)) != pid)
    {
      if (got_pid < 0 && errno == ECHILD)
	{
	  status.w_termsig = status.w_retcode = 0;    /* <-- NOTE */
	  break;
	}
      else if (got_pid < 0 && errno != EINTR)
	programming_error ("got errno %d while waiting for %d", errno, pid);
    }


The hitch here is that w_termsig expands to bytes.low & 0x7f.  Hence the
entire expression expands to

       status.bytes.low & 0x7f = status.w_retcode = 0;

What is the intention here?  I'm just curious.  If the attempt is being
made to zero out the lower seven bits of status.bytes.low, wouldn't

       status.bytes.low &= 0x80;

be more appropriate?

I don't claim to be a wizard.  I'm just trying to compile Bash on my
Xenix box.

If this is a silly question, and I should have seen what was going on
I'd still like to know about my mistake.

   -Richard L. Goerwitz              goer%sophist@uchicago.bitnet
   goer@sophist.uchicago.edu         rutgers!oddjob!gide!sophist!goer

bfox@sbphy.mit.edu (Brian Fox) (02/10/90)

   Date: 9 Feb 90 18:37:47 GMT
   From: asuvax!ncar!tank!sophist!goer@cs.utexas.edu  (Richard Goerwitz)
   Organization: University of Chicago
   Sender: bug-bash-request@prep.ai.mit.edu

   Silly question?

No.

   What is the intention here?  I'm just curious.  If the attempt is being
   made to zero out the lower seven bits of status.bytes.low, wouldn't

	  status.bytes.low &= 0x80;

   be more appropriate?

   I don't claim to be a wizard.  I'm just trying to compile Bash on my
   Xenix box.

   If this is a silly question, and I should have seen what was going on
   I'd still like to know about my mistake.

You (among others) found this bug in Bash.  The problem was a poor
description for the structure returned by wait () on little-endian
machines.  We have since fixed the description, and here it is:

#ifdef NO_WAIT_H
#ifdef LITTLE_ENDIAN
union wait
  {
    int	w_status;		/* used in syscall */

    /* Terminated process status. */
    struct
      {
	unsigned short
	  w_Termsig  : 7,	/* termination signal */
	  w_Coredump : 1,	/* core dump indicator */
	  w_Retcode  : 8,	/* exit code if w_termsig==0 */
	  w_Fill1    : 16;	/* high 16 bits unused */
      } w_T;

    /* Stopped process status.  Returned
       only for traced children unless requested
       with the WUNTRACED option bit. */
    struct
      {
	unsigned short
	  w_Stopval : 8,	/* == W_STOPPED if stopped */
	  w_Stopsig : 8,	/* actually zero on XENIX */
	  w_Fill2   : 16;	/* high 16 bits unused */
      } w_S;
  };
#endif /* LITTLE_ENDIAN */

#define	w_termsig w_T.w_Termsig
#define w_coredump w_T.w_Coredump
#define w_retcode w_T.w_Retcode
#define w_stopval w_S.w_Stopval
#define w_stopsig w_S.w_Stopsig

#define	WSTOPPED 0177
#define WIFSTOPPED(x) (((x) . w_stopval) == WSTOPPED)
#define WIFEXITED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) == 0))
#define WIFSIGNALED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) != 0))
#endif /* NO_WAIT_H */

bengsig@oracle.nl (Bjorn Engsig) (02/13/90)

Article <7551@tank.uchicago.edu> by goer@sophist.UUCP (Richard Goerwitz) says:
|  struct {                           /* clever way of getting at
|    unsigned char low;                * wait's high and low 
|  }                                   * /
|  bytes;
|#define w_termsig bytes.low & 0x7f    /* mask out eighth bit */
|	  status.w_termsig = status.w_retcode = 0;    /* <-- NOTE */
|
|[...] w_termsig expands to bytes.low & 0x7f [and the] expression expands to
|
|       status.bytes.low & 0x7f = status.w_retcode = 0;
In many systsem, a system header file will define the struct with bitfields
named termsig, etc. but the bash implementors define these as masks to help
those without the right header file.  They then just this incorrectly, and you
should use the masking status.bytes.low &= 0x80 as you suggest.
-- 
Bjorn Engsig,	Domain:		bengsig@oracle.nl, bengsig@oracle.com
		Path:		uunet!{mcsun!orcenl,oracle}!bengsig