]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
merge with 1.4
authorJim Meyering <jim@meyering.net>
Wed, 20 Jan 1993 04:29:09 +0000 (04:29 +0000)
committerJim Meyering <jim@meyering.net>
Wed, 20 Jan 1993 04:29:09 +0000 (04:29 +0000)
lib/regex.c
old/textutils/ChangeLog
src/tail.c

index a0e4e8950e56dae0ce34fc0b5b128a9ea3bcec10..eda11b5350a09d626ef973f7d76129061d8a8cfd 100644 (file)
@@ -3,7 +3,7 @@
    (Implements POSIX draft P10003.2/D11.2, except for
    internationalization features.)
 
-   Copyright (C) 1985, 89, 90, 91, 92 Free Software Foundation, Inc.
+   Copyright (C) 1993 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@
 /* We need this for `regex.h', and perhaps for the Emacs include files.  */
 #include <sys/types.h>
 
-#if defined (HAVE_CONFIG_H) || defined (emacs)
+#ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
@@ -2197,18 +2197,20 @@ compile_range (p_ptr, pend, translate, syntax, b)
   unsigned this_char;
 
   const char *p = *p_ptr;
+  int range_start, range_end;
   
-  /* Even though the pattern is a signed `char *', we need to fetch into
-     `unsigned char's.  Reason: if the high bit of the pattern character
-     is set, the range endpoints will be negative if we fetch into a
-     signed `char *'.  */
-  unsigned char range_end;
-  unsigned char range_start = p[-2];
-
   if (p == pend)
     return REG_ERANGE;
 
-  PATFETCH (range_end);
+  /* Even though the pattern is a signed `char *', we need to fetch
+     with unsigned char *'s; if the high bit of the pattern character
+     is set, the range endpoints will be negative if we fetch using a
+     signed char *.
+
+     We also want to fetch the endpoints without translating them; the 
+     appropriate translation is done in the bit-setting loop below.  */
+  range_start = ((unsigned char *) p)[-2];
+  range_end   = ((unsigned char *) p)[0];
 
   /* Have to increment the pointer into the pattern string, so the
      caller isn't still at the ending character.  */
@@ -3989,21 +3991,13 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
 
             /* If we're at the end of the pattern, we can change.  */
             if (p2 == pend)
-              { /* But if we're also at the end of the string, we might
-                   as well skip changing anything.  For example, in `a+'
-                   against `a', we'll have already matched the `a', and
-                   I don't see the the point of changing the opcode,
-                   popping the failure point, finding out it fails, and
-                   then going into our endgame.  */
-                if (d == dend)
-                  {
-                    p = pend;
-                    DEBUG_PRINT1 ("  End of pattern & string => done.\n");
-                    continue;
-                  }
-                
+             {
+               /* Consider what happens when matching ":\(.*\)"
+                  against ":/".  I don't really understand this code
+                  yet.  */
                p[-3] = (unsigned char) pop_failure_jump;
-                DEBUG_PRINT1 ("  End of pattern => pop_failure_jump.\n");
+                DEBUG_PRINT1
+                  ("  End of pattern: change to `pop_failure_jump'.\n");
               }
 
             else if ((re_opcode_t) *p2 == exactn
@@ -4875,9 +4869,18 @@ regerror (errcode, preg, errbuf, errbuf_size)
     char *errbuf;
     size_t errbuf_size;
 {
-  const char *msg
-    = re_error_msg[errcode] == NULL ? "Success" : re_error_msg[errcode];
-  size_t msg_size = strlen (msg) + 1; /* Includes the null.  */
+  const char *msg;
+  size_t msg_size;
+
+  if (errcode < 0
+      || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0])))
+    /* Only error codes returned by the rest of the code should be passed 
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
   
   if (errbuf_size != 0)
     {
index a4fa7d7ba69fc32c13b19478183ef6e165d5d1f1..3d68bba0b76264956d08a88523ed665561a07f44 100644 (file)
@@ -1,3 +1,22 @@
+Tue Jan 19 13:35:24 1993  David J. MacKenzie  (djm@kropotkin.gnu.ai.mit.edu)
+
+       * Version 1.4.
+
+       * system.h: Try BBSIZE if BSIZE isn't defined.
+       From Tony Robinson <ajr@eng.cam.ac.uk>.
+
+Sat Dec 12 12:37:00 1992  David J. MacKenzie  (djm@kropotkin.gnu.ai.mit.edu)
+
+       * tail.c (tail_forever): Use an array of file descriptors
+       instead of forking processes.
+       (dump_remainder): Return number of bytes read.
+       (tail_file): Fill in the new array.
+       From Ian Lance Taylor.
+
+Fri Dec 11 17:18:16 1992  David J. MacKenzie  (djm@kropotkin.gnu.ai.mit.edu)
+
+       * system.h: Only define index, bcmp, etc. if not already defined.
+
 Tue Dec  8 10:31:14 1992  Jim Meyering  (meyering@idefix.comco.com)
 
        * tr.c (is_char_class_member): Remove unreached return after abort.
index be0978fe42a0af786c6b1beb0d377dfdb156e679..138c22894afb9cc5f7877c3f171661989d798b7d 100644 (file)
@@ -70,6 +70,9 @@ static int forever_multiple;
 /* Array of file descriptors if forever_multiple is 1.  */
 static int *file_descs;
 
+/* Array of file sizes if forever_multiple is 1.  */
+static off_t *file_sizes;
+
 /* If nonzero, count from start of file instead of end. */
 static int from_start;
 
@@ -96,7 +99,7 @@ static int tail_bytes ();
 static int tail_file ();
 static int tail_lines ();
 static long atou();
-static void dump_remainder ();
+static long dump_remainder ();
 static void tail_forever ();
 static void parse_unit ();
 static void usage ();
@@ -263,6 +266,7 @@ main (argc, argv)
       forever_multiple = 1;
       forever = 0;
       file_descs = (int *) xmalloc ((argc - optind) * sizeof (int));
+      file_sizes = (off_t *) xmalloc ((argc - optind) * sizeof (off_t));
     }
 
   if (header_mode == always
@@ -297,6 +301,7 @@ tail_file (filename, number, filenum)
      int filenum;
 {
   int fd, errors;
+  struct stat stats;
 
   if (!strcmp (filename, "-"))
     {
@@ -306,7 +311,26 @@ tail_file (filename, number, filenum)
        write_header (filename);
       errors = tail (filename, 0, number);
       if (forever_multiple)
-       file_descs[filenum] = errors ? -1 : 0;
+       {
+         if (fstat (0, &stats) < 0)
+           {
+             error (0, errno, "standard input");
+             errors = 1;
+           }
+         else if (!S_ISREG (stats.st_mode))
+           {
+             error (0, 0,
+                    "standard input: cannot follow end of non-regular file");
+             errors = 1;
+           }
+         if (errors)
+           file_descs[filenum] = -1;
+         else
+           {
+             file_descs[filenum] = 0;
+             file_sizes[filenum] = stats.st_size;
+           }
+       }
     }
   else
     {
@@ -326,13 +350,26 @@ tail_file (filename, number, filenum)
          errors = tail (filename, fd, number);
          if (forever_multiple)
            {
+             if (fstat (fd, &stats) < 0)
+               {
+                 error (0, errno, "%s", filename);
+                 errors = 1;
+               }
+             else if (!S_ISREG (stats.st_mode))
+               {
+                 error (0, 0, "%s: cannot follow end of non-regular file");
+                 errors = 1;
+               }
              if (errors)
                {
                  close (fd);
                  file_descs[filenum] = -1;
                }
              else
-               file_descs[filenum] = fd;
+               {
+                 file_descs[filenum] = fd;
+                 file_sizes[filenum] = stats.st_size;
+               }
            }
          else
            {
@@ -821,21 +858,26 @@ start_lines (filename, fd, number)
   return 0;
 }
 
-/* Display file FILENAME from the current position in FD
-   to the end.  If `forever' is nonzero, keep reading from the
-   end of the file until killed. */
+/* Display file FILENAME from the current position in FD to the end.
+   If `forever' is nonzero, keep reading from the end of the file
+   until killed.  Return the number of bytes read from the file.  */
 
-static void
+static long
 dump_remainder (filename, fd)
      char *filename;
      int fd;
 {
   char buffer[BUFSIZE];
   int bytes_read;
+  long total;
 
+  total = 0;
 output:
   while ((bytes_read = read (fd, buffer, BUFSIZE)) > 0)
-    xwrite (1, buffer, bytes_read);
+    {
+      xwrite (1, buffer, bytes_read);
+      total += bytes_read;
+    }
   if (bytes_read == -1)
     error (1, errno, "%s", filename);
   if (forever)
@@ -843,174 +885,61 @@ output:
       sleep (1);
       goto output;
     }
+  return total;
 }
 
-#ifndef SIGUSR1
-#define SIGUSR1 SIGSYS
-#endif
-
-/* To support tail_forever we use a signal handler that just quietly
-   exits.  We are going to fork once for each file; we send a SIGUSR1
-   to kill the children if an error occurs.  */
-
-static RETSIGTYPE
-sigusr1 (sig)
-     int sig;
-{
-  exit (0);
-}
-
-/* Print error message MESSAGE for errno ERRNUM;
-   send SIGUSR1 to the KIDS processes in PIDS;
-   exit with status 1.  */
-
-static void
-kill_kids (errnum, message, pids, kids)
-     int errnum;
-     char *message;
-     int *pids;
-     int kids;
-{
-  int i;
-
-  error (0, errnum, message);
-  for (i = 0; i < kids; i++)
-    kill (pids[i], SIGUSR1);
-  exit (1);
-}
-
-/* The number of bytes that a pipe can hold (atomic read or write).  */
-#ifndef PIPE_BUF
-#define PIPE_BUF 512
-#endif
-
-/* Tail NFILES (>1) files forever until killed.  The file names are in NAMES.
-   The open file descriptors are in `file_descs'.  Fork a process for each
-   file, let all the processes write to a single pipe, and then read
-   the pipe.  */
-/* Should we reap the zombies with wait?  */
+/* Tail NFILES (>1) files forever until killed.  The file names are in
+   NAMES.  The open file descriptors are in `file_descs', and the size
+   at which we stopped tailing them is in `file_sizes'.  We loop over
+   each of them, doing an fstat to see if they have changed size.  If
+   none of them have changed size in one iteration, we sleep for a
+   second and try again.  We do this until the user interrupts us.  */
 
 static void
 tail_forever (names, nfiles)
      char **names;
      int nfiles;
 {
-  int pipe_descs[2];
-  int *pids;
-  int i;
-  char *buffer = xmalloc (PIPE_BUF); /* malloc assures `int' alignment.  */
-  int bytes_read;
-  int ilast;
-
-  if (pipe (pipe_descs) < 0)
-    error (1, errno, "cannot make pipe");
-
-  pids = (int *) xmalloc (nfiles * sizeof (int));
+  int last;
 
-  /* fork once for each file.  This approach uses one process and
-     one file descriptor for each file we tail.
-     More resource-efficient approaches would be:
+  last = -1;
 
-     1.  Keep an off_t array of the last-seen sizes of the files,
-     and fstat them each in turn, watching for growth.
-     This would be more portable, but still use the same number of
-     file descriptors, and would probably use more CPU.
-     For pipes, perhaps a separate process would have to be forked to
-     read from the pipe and write to a temporary file.
-
-     2.  Keep an off_t array, but only keep recently changed files open
-     and use stat for the others, opening them only if they change.
-     This would save file descriptors, to allow tail -f on a large number
-     of files.  It's probably not worth the trouble for most uses, though,
-     and GNU won't have arbitrary limits on things like file descriptors.  */
-
-  signal (SIGUSR1, sigusr1);
-
-  for (i = 0; i < nfiles; i++)
+  while (1)
     {
-      if (file_descs[i] == -1)
-       continue;
-      
-      pids[i] = fork ();
-      if (pids[i] == -1)
-       kill_kids (errno, "cannot fork", pids, i);
-      if (pids[i] == 0)
-       {
-         /* Child.  */
-         int offset;
+      int i;
+      int changed;
 
-         close (pipe_descs[0]);
-
-         /* Each child reads continually from a file and writes to
-            the pipe.  Each write to the pipe is the index of the file
-            being read, followed by the number of bytes read from the
-            file, followed by the actual data.  Each child is
-            careful to write no more than PIPE_BUF bytes to the pipe,
-            so that the data from the various children do not get
-            intermixed.  */
-
-         /* The file index for this child is always the same.  */
-         *(int *) buffer = i;
+      changed = 0;
+      for (i = 0; i < nfiles; i++)
+       {
+         struct stat stats;
 
-         offset = sizeof i + sizeof bytes_read;
+         if (file_descs[i] < 0)
+           continue;
+         if (fstat (file_descs[i], &stats) < 0)
+           {
+             error (0, errno, "%s", names[i]);
+             file_descs[i] = -1;
+             continue;
+           }
+         if (stats.st_size == file_sizes[i])
+           continue;
 
-         while (1)
+         /* This file has changed size.  Print out what we can, and
+            then keep looping.  */
+         if (i != last)
            {
-             while ((bytes_read = read (file_descs[i], buffer + offset,
-                                        PIPE_BUF - offset)) > 0)
-               {
-                 *(int *) (buffer + sizeof i) = bytes_read;
-                 if (write (pipe_descs[1], buffer, offset + bytes_read)
-                     != offset + bytes_read)
-                   _exit (0);  /* Somebody killed our parent?  */
-               }
-             if (bytes_read == -1)
-               {
-                 error (0, errno, "%s", names[i]);
-                 _exit (1);
-               }
-             sleep (1);
+             write_header (names[i]);
+             last = i;
            }
+         changed = 1;
+         file_sizes[i] += dump_remainder (names[i], file_descs[i]);
        }
-    }
-
-  /* Parent.  */
-
-  close (pipe_descs[1]);
 
-  /* Wait for input to come in on the pipe.  Read the file index
-     and the number of bytes.  Then read that many bytes and print
-     them out.  Repeat until all the children have closed the pipe.  */
-
-  ilast = -1;
-
-  while ((bytes_read = read (pipe_descs[0], buffer,
-                            sizeof i + sizeof bytes_read)) > 0)
-    {
-      int igot;                        /* Index of latest process that wrote.  */
-
-      if (bytes_read != sizeof i + sizeof bytes_read)
-       kill_kids (errno, "read error", pids, nfiles); /* Yikes.  */
-
-      /* Extract the file index and the number of bytes.  */
-      igot = *(int *) buffer;
-      bytes_read = *(int *) (buffer + sizeof i);
-
-      if (print_headers && igot != ilast)
-       write_header (names[igot]);
-      ilast = igot;
-
-      errno = 0;
-      if (read (pipe_descs[0], buffer, bytes_read) != bytes_read)
-       kill_kids (errno, "read error", pids, nfiles);
-      if (write (1, buffer, bytes_read) != bytes_read)
-       kill_kids (errno, "write error", pids, nfiles);
+      /* If none of the files changed size, sleep.  */
+      if (! changed)
+       sleep (1);
     }
-       
-  for (i = 0; i < nfiles; i++)
-    kill (pids[i], SIGUSR1);
-
-  free (buffer);
 }
 
 static void