[gnu.bash.bug] Bash 1.03, lots of comments + bugfixes for SYSV

ra@is.uu.no (Robert Andersson) (09/04/89)

I have spent today getting bash 1.03 up and running on my NCR Tower 
running SYSV.2. It was *not* as easy as I hoped.

Anyway, here's various comments and questions that arised from the
exercise. At the end you will also find some diff's.

Bash is really promising, but still needs some work. Not surprising,
given its young age. Keep up the good work Brian. 


1. Some files had names > 14 chars, SYSV doesn't handle this :-(
Not a big deal, but you might want to rename them. 
longest_signal_name.c        (What's the point in this program anyway?) 
readline/*.texinfo

2. readline/readline.c
Signal handling is disabled for SYSV , ie. SIGINT and SIGQUIT is
turned off at the terminal driver level. Why? I can fix this easily but
wondered if there was any real reason for this.
If FIONREAD was not defined rl_gather_tyi failed to compile. 
Definitions of getpwuid() and getpwent() were wrong.
readline_default_binding did not have code for SYSV termio-style ioctls.
See context diffs at the end.
I still have one unresolved problem in readline:
rl_gather_tyi loses every second character of typeahead if FIONREAD is
not defined. I believe it is caused by the two lines,
       if (tem < ibuffer_len)
         char_avail = 0;
but it's not quite clear what should be done instead.

3. builtins.c
The helptexts for 'test' and 'set' break the limit on text literal
length in my C-compiler. I expect the same to happen on a number of
other compilers. What does the pANS say about this? Anyway, you might
consider doing this differently for maximum portability.

4. builtins.c
Neither of the two 'echo' implementations are SYSV compatible.

5. general.c
Should not define the functions bcopy, index and rindex for SYSV.
Use macros mapping them to memcpy, strchr and strrchr in one of the .h
files instead. jobs.c makes an attempt at this, but does it based on a
USG #if conditional, and USG is defined nowhere.

6. jobs.h
The #if's should probably be rearranged so that SYSV machines as a
default defines union wait etc.

7. Makefile
The rule for $(TERMCAP) caused make to enter an endless loop. I simply
removed the dependencies and rules for this target.

8. documentation/bash.texinfo
Emacs 18.54 texinfo-format-buffer fails to format this one. The line 
"foo @result{} bar" gives the error message:
@result is not handled by texinfo

9. nojobs.c
Only had BSD-style ioctls in get_tty_state and set_tty_state.
Merged in a lot of changes that apperead to only have been done in
jobs.c. See context diffs at the end.

--
Robert Andersson, International Systems, Oslo, Norway
Internet:         ra@is.uu.no
UUCP:             ...!{uunet,mcvax,ifi}!is.uu.no!ra
	

*** orig/nojobs.c	Sat Sep  2 18:54:08 1989
--- ./nojobs.c	Sun Sep  3 21:18:30 1989
***************
*** 26,37 ****
--- 26,47 ----
  #include "config.h"
  #include "general.h"
  #include "jobs.h"
+ #include "quit.h"
  
  #ifndef SIGABRT
  #define SIGABRT SIGIOT
  #endif
  
+ #define NEW_TTY_DRIVER
+ #if defined (SYSV) || defined(hpux)
+ #undef NEW_TTY_DRIVER
+ #include <termio.h>
+ #else
+ #include <sgtty.h>
+ #endif
+ 
  #ifndef SYSV
+ #include <sys/file.h>
  #include <sys/time.h>
  #include <sys/resource.h>
  /* The total amount of system time spent running processes for me. */
***************
*** 43,48 ****
--- 53,60 ----
  struct timeval total_usertime = {0, 0};
  long user_minutes_used = 0;
  int user_seconds_used = 0;
+ #else
+ #include <fcntl.h>
  #endif
  
  int last_made_pid;
***************
*** 53,58 ****
--- 65,71 ----
   */
  initialize_jobs ()
  {
+   get_tty_state ();
  }
  
  /*
***************
*** 92,100 ****
--- 105,125 ----
       int async_p;
  {
    int pid;
+ #ifdef SYSV
+   SigHandler *old_int;
+ #else
+   int oldmask;
+ #endif
  
    /* Discard saved memory. */
    free (command);
+   command = (char *)NULL;
+ 
+ #ifdef SYSV
+   old_int = signal (SIGINT, SIG_IGN);
+ #else
+   oldmask = sigblock (sigmask (SIGINT));
+ #endif
  
    /* Make new environment array if neccessary. */
    maybe_make_export_env ();
***************
*** 102,107 ****
--- 127,139 ----
    /* Create the child, handle severe errors. */
    if ((pid = fork ()) < 0)
      {
+       sighandler throw_to_top_level ();
+ 
+ #ifdef SYSV
+       (void) signal (SIGINT, old_int);
+ #else
+       sigsetmask (oldmask);
+ #endif
        report_error ("Memory exhausted or process overflow!");
        throw_to_top_level ();
      }
***************
*** 108,113 ****
--- 140,147 ----
  
    if (!pid)
      {
+       signal (SIGTERM, SIG_DFL);
+ 
        /*
         * Ignore INT and QUIT in asynchronous children.
         */
***************
*** 129,142 ****
         * In the parent.
         */
        last_made_pid = pid;
-       remember_pid (pid);
- 
        if (async_p)
  	last_asynchronous_pid = pid;
      }
    return (pid);
  }
  
  /*
   * Wait for pid (one of our children) to terminate.
   */
--- 163,213 ----
         * In the parent.
         */
        last_made_pid = pid;
        if (async_p)
  	last_asynchronous_pid = pid;
+ #ifdef SYSV
+       (void) signal (SIGINT, old_int);
+ #endif
      }
+ #ifndef SYSV
+   sigsetmask (oldmask);
+ #endif
    return (pid);
  }
  
+ wait_for_single_pid (pid)
+      int pid;
+ {
+   int got_pid;
+   union wait status;
+ 
+   while ((got_pid = wait (&status)) != pid)
+     {
+       if (got_pid < 0)
+ 	{
+ 	  if (errno != EINTR && errno != ECHILD)
+ 	    file_error ("wait");
+ 	  break;
+ 	}
+       QUIT;
+     }
+   QUIT;
+ }
+ 
+ wait_for_background_pids ()
+ {
+   int got_pid;
+   union wait status;
+ 
+   got_pid = wait (&status);
+   if (got_pid < 0)
+     {
+       if (errno != EINTR && errno != ECHILD)
+ 	file_error ("wait");
+     }
+   QUIT;
+ }
+ 
  /*
   * Wait for pid (one of our children) to terminate.
   */
***************
*** 143,175 ****
  wait_for (pid)
       int pid;
  {
!   int got_pid, return_val, oldmask;
    union wait status;
- #ifndef SYSV
-   SigHandler *old_int, *old_quit;
- #endif
- 
- #ifdef SYSV
-   oldmask = sigignore (SIGINT);
- #else
-   oldmask = sigblock (sigmask (SIGINT));
- #endif
  
    while ((got_pid = wait (&status)) != pid)
      {
        if (got_pid < 0 && errno != EINTR)
! 	programming_error ("got errno %d while waiting for %d", errno, pid);
      }
  
- #ifdef SYSV
-   sigrelse (oldmask);
- #else
-   sigsetmask (oldmask);
- #endif
- 
    /* Default return value. */
    return_val = status.w_retcode & 0x7f;
  
    if (status.w_termsig != 0 && status.w_termsig != WSTOPPED)
      {
        extern char *sys_siglist[];
--- 214,239 ----
  wait_for (pid)
       int pid;
  {
!   int got_pid, return_val;
    union wait status;
  
    while ((got_pid = wait (&status)) != pid)
      {
        if (got_pid < 0 && errno != EINTR)
! 	file_error ("wait");
      }
  
    /* Default return value. */
    return_val = status.w_retcode & 0x7f;
  
+   /* If the command did not exit cleanly, or the job is just
+      being stopped, then reset the tty state back to what it
+      was before this command. */
+   if (status.w_termsig != 0 || WIFSTOPPED (status))
+     set_tty_state ();
+   else
+     get_tty_state ();
+ 
    if (status.w_termsig != 0 && status.w_termsig != WSTOPPED)
      {
        extern char *sys_siglist[];
***************
*** 178,184 ****
  	fprintf (stderr, " (core dumped)");
        fprintf (stderr, "\n");
        return_val = status.w_termsig + 128;
-       get_tty_state ();
      }
    return (return_val);
  }
--- 242,247 ----
***************
*** 186,192 ****
--- 249,259 ----
  /* When we end a job abnormally, or if we stop a job, we set the tty to the
     state kept in here.  When a job ends normally, we set the state in here
     to the state of the tty. */
+ #ifdef NEW_TTY_DRIVER
  static struct sgttyb shell_tty_info;
+ #else
+ static struct termio shell_tty_info;
+ #endif
  
  /* Fill the contents of shell_tty_info with the current tty info. */
  get_tty_state ()
***************
*** 194,200 ****
--- 261,271 ----
    int tty = open ("/dev/tty", O_RDONLY);
    if (tty != -1)
      {
+ #ifdef NEW_TTY_DRIVER
        ioctl (tty, TIOCGETP, &shell_tty_info);
+ #else
+       ioctl (tty, TCGETA, &shell_tty_info);
+ #endif
        close (tty);
      }
  }
***************
*** 205,211 ****
--- 276,286 ----
    int tty = open ("/dev/tty", O_RDONLY);
    if (tty != -1)
      {
+ #ifdef NEW_TTY_DRIVER
        ioctl (tty, TIOCSETN, &shell_tty_info);
+ #else
+       ioctl (tty, TCSETAW, &shell_tty_info);
+ #endif
        close (tty);
      }
  }
*** orig/readline.c	Sat Sep  2 18:54:16 1989
--- readline/readline.c	Sat Sep  2 19:31:55 1989
***************
*** 60,66 ****
  
  #include <pwd.h>
  #ifdef SYSV
! struct pwd *getpwuid (), *getpwent ();
  #endif
  
  #define HACK_TERMCAP_MOTION
--- 60,66 ----
  
  #include <pwd.h>
  #ifdef SYSV
! struct passwd *getpwuid (), *getpwent ();
  #endif
  
  #define HACK_TERMCAP_MOTION
***************
*** 526,536 ****
  #ifdef FIONREAD
    ioctl (tty, FIONREAD, &chars_avail);
  #else
!   fcntl (tty, F_SETFL, O_NDELAY);
    chars_avail = read (tty, &input, 1);
!   if (chars_avail == -1 && errno == EAGAIN)
      return;
-   fcntl (fileno (stdin), F_SETFL, 0);
  #endif
  
    tem = ibuffer_space ();
--- 526,536 ----
  #ifdef FIONREAD
    ioctl (tty, FIONREAD, &chars_avail);
  #else
!   fcntl (tty, F_SETFL, fcntl(tty, F_GETFL, 0) | O_NDELAY);
    chars_avail = read (tty, &input, 1);
!   fcntl (tty, F_SETFL, fcntl(tty, F_GETFL, 0) & ~O_NDELAY);
!   if (chars_avail < 1)
      return;
  #endif
  
    tem = ibuffer_space ();
***************
*** 686,691 ****
--- 686,692 ----
     equivalents. */
  readline_default_bindings ()
  {
+ #ifdef NEW_TTY_DRIVER
  #ifdef TIOCGETP
    struct sgttyb ttybuff;
    int tty = fileno (rl_instream);
***************
*** 708,713 ****
--- 709,725 ----
    }
  #endif /* TIOCGLTC */
  #endif /*  TIOCGETP */
+ #else  /* !defined (NEW_TTY_DRIVER) */
+   struct termio ttybuff;
+   int tty = fileno (rl_instream);
+ 
+   if (ioctl (tty, TCGETA, &ttybuff) != -1)
+     {
+       keymap[ttybuff.c_cc[VERASE]] = rl_rubout;
+       keymap[ttybuff.c_cc[VKILL]] = rl_unix_line_discard;
+     }
+ 
+ #endif /*  NEW_TTY_DRIVER */
  }