[comp.os.minix] bug fix for sh

wayne@csri.toronto.edu (Wayne Hayes) (12/26/90)

I finally got sick of waiting for tail(1) to chug through huge files, so I
added a little function (only about 10 lines) called ftail(), for "file
tail".  It is only used if the file for tail is given on the command
line (ie, is not a pipe), and the '-' (as opposed to '+') option is used.
Ftail() seeks to the end of the real file, then seeks backwards by
256 * (# of requested tail lines), and then continues normally by calling
the tail() function.  For files greater than about 100K, it's nicely
faster.  For files greater than a megabyte, it's instant as opposed to
60 seconds or so on my 33MHz 386 running Minix-386.

I also increased the circular buffer size for non-8088 machines.

*** tail.c.1.5	Mon Jun 27 09:01:02 2011
--- tail.c	Wed Dec 26 13:45:19 1990
***************
*** 1,5 ****
! /* tail - print the end of a file */
! 
  #include <stdio.h>
  
  #define TRUE 1
--- 1,12 ----
! /* tail - print the end of a file -- original by Andy Tanenbaum??? */
! 
! /* Modified to be "smart" with non-pipes, to seek to end and then backwards
!    a bit so it doesn't take forever to execute ``tail {hugefile}''.
! 	- Wayne Hayes, 1990 Dec 25.  (What do *you* do on Christmas day?  :-)
! */
! 
! #include <sys/types.h>	/* for unistd.h */
! #include <unistd.h>	/* for fseek */
  #include <stdio.h>
  
  #define TRUE 1
***************
*** 8,13 ****
--- 15,24 ----
  #define TAB '\t'
  #define NEWL '\n'
  
+ /* When seeking backwards from EOF, we seek back by MAX_ASSUMED_LINE times
+    the number of requested tail lines. */
+ #define MAX_ASSUMED_LINE 256
+ 
  int lines, chars;
  char buff[BUFSIZ];
  
***************
*** 53,64 ****
  	exit(1);
    }
    if (argc == 0) tail(stdin, count);
- 
    else if ((input = fopen(*argv, "r")) == NULL) {
  	fprintf(stderr, "tail: can't open %s\n", *argv);
  	exit(1);
    } else {
! 	tail(input, count);
  	fclose(input);
    }
  
--- 64,74 ----
  	exit(1);
    }
    if (argc == 0) tail(stdin, count);
    else if ((input = fopen(*argv, "r")) == NULL) {
  	fprintf(stderr, "tail: can't open %s\n", *argv);
  	exit(1);
    } else {
! 	ftail(input, count);	/* use the smarter back-seeking tail */
  	fclose(input);
    }
  
***************
*** 87,93 ****
  /* Tail - print 'count' lines/chars */
  
  #define INCR(p)  if (p >= end) p=cbuf ; else p++
! #define BUF_SIZE 4098
  
  char cbuf[BUF_SIZE];
  
--- 97,108 ----
  /* Tail - print 'count' lines/chars */
  
  #define INCR(p)  if (p >= end) p=cbuf ; else p++
! 
! #if defined(INTEL_32BITS) | (CHIP == M68000) | (CHIP == SPARC)
! #define BUF_SIZE 40980
! #else
! #define BUF_SIZE 4098
! #endif
  
  char cbuf[BUF_SIZE];
  
***************
*** 143,145 ****
--- 158,170 ----
    }				/* end else */
  
  }				/* end tail */
+ 
+ 
+ ftail(in, goal)
+ FILE *in;
+ int goal;
+ {
+   if(goal < 0)
+   	fseek(in, (long)goal * MAX_ASSUMED_LINE, SEEK_END);
+   return tail(in, goal);
+ }				/* end ftail */
---------------------- cut here ------------------

I've also found a bug in the shell.  Suppose I have the following shell script:

#!/bin/sh
while :; do
	fortune
done | more


(Hey, what else can you do on Christmas eve?  :-)

When I type 'q' at the more(1) prompt, the script should exit, right?  Well,
it does, kindof.  The shell exits back to the login shell, but the loop
continues on forever!  Ie, in the background you will have 'fortune' and
an extra shell hogging CPU.  The *really* weird thing is that if I then
press ^C while sitting in the *login* shell, the background process stops.

I'm not sure if this is an indication of some nasty bug in the kernel,
but for now I have a fix.  In sh3.c, I've added an extra line that checks
to see if it's an interactive shell.  If not (ie, it's a shell script),
and one of the children dies via a signal (in the case above the signal
is "Broken pipe"), then we send ourselves the same signal, because we
should probably die too if one of our children dies.  This may have
nasty consequences for the trap(1) command in the shell if you're not
careful, so if you're not sure you may not want to apply this patch.
(It's only one line.)


*** sh3.c.1.5	Wed Dec 26 16:25:13 1990
--- sh3.c	Wed Dec 26 15:48:12 1990
***************
*** 505,510 ****
--- 505,513 ----
  					prs(" - core dumped");
  				if (rv >= NSIGNAL || signame[rv])
  					prs("\n");
+ 				/* if we are not interactive (ie we are a shell script), we
+ 				** should receive the same signal. Wayne Hayes 1990 Dec 24 */
+ 				if(!talking) kill(getpid(), rv);
  				rv = -1;
  			} else
  				rv = WAITVAL(s);

--------------------- cut here ---------------------------

-- 
"Dad, what should I be when I grow up?"
"Honest." -- Robert M. Pirsig, _Zen and the Art of Motorcycle Maintenence_.

Wayne Hayes	INTERNET: wayne@csri.utoronto.ca	CompuServe: 72401,3525