Initial revision
authorGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Tue, 29 Oct 1991 22:35:01 +0000 (22:35 +0000)
committerGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Tue, 29 Oct 1991 22:35:01 +0000 (22:35 +0000)
v7/src/microcode/bchdrn.c [new file with mode: 0644]
v7/src/microcode/bchdrn.h [new file with mode: 0644]
v7/src/microcode/bchutl.c [new file with mode: 0644]

diff --git a/v7/src/microcode/bchdrn.c b/v7/src/microcode/bchdrn.c
new file mode 100644 (file)
index 0000000..335a721
--- /dev/null
@@ -0,0 +1,512 @@
+/* -*- C -*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/bchdrn.c,v 1.1 1991/10/29 22:34:41 jinx Exp $
+
+Copyright (c) 1991 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+/* Drone program for overlapped I/O in bchscheme. */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "bchdrn.h"
+
+#define DEBUG
+
+extern char * EXFUN (error_name, (int));
+extern int EXFUN (retrying_file_operation,
+                 (/* no prototype because (const char *) != (char *) */
+                  int (*)(),
+                  int, char *, long, long, char *, char *, long *,
+                  int (*)(char *, char *)));
+\f
+#ifdef HAVE_SYSV_SHARED_MEMORY
+
+static struct
+{
+  char * program_name;
+  char * file_name;            /* gc file name */
+  int shmid;                   /* shared memory descriptor */
+  int tdron;                   /* total number of drones */
+  int nbuf;                    /* total number of buffers */
+  long bufsiz;                 /* size of each buffer in bytes */
+  int sdron;                   /* index of first drone to start */
+  int ndron;                   /* number of drones to start */
+  int keep_p;                  /* keep the gc file if Scheme dies? */
+} arguments;
+
+struct argdesc
+{
+  char * name;
+  char * format;
+  PTR location;
+};
+
+static char string_a[] = "%s";
+#define STRING_FMT &string_a[0]
+
+static char decimal_int_a[] = "%d";
+#define DECIMAL_INT_FMT &decimal_int_a[0]
+
+static char decimal_long_a[] = "%ld";
+#define DECIMAL_LONG_FMT &decimal_long_a[0]
+
+static struct argdesc command_line[] =
+{
+  { "program_name",    STRING_FMT,             &arguments.program_name },
+  { "file_name",       STRING_FMT,             &arguments.file_name },
+  { "shmid",           DECIMAL_INT_FMT,        &arguments.shmid },
+  { "tdron",           DECIMAL_INT_FMT,        &arguments.tdron },
+  { "nbuf",            DECIMAL_INT_FMT,        &arguments.nbuf },
+  { "bufsiz",          DECIMAL_LONG_FMT,       &arguments.bufsiz },
+  { "sdron",           DECIMAL_INT_FMT,        &arguments.sdron },
+  { "ndron",           DECIMAL_INT_FMT,        &arguments.ndron },
+  { "keep_gc_file",    DECIMAL_INT_FMT,        &arguments.keep_p }
+};
+
+static int gc_fid = -1;
+static char * shared_memory;
+static struct buffer_info * gc_buffers;
+static struct drone_info * myself;
+static pid_t parent_pid, * wait_pid;
+static jmp_buf abort_point;
+\f
+static void
+DEFUN (shutdown, (sig), int sig)
+{
+  myself->state = drone_dead;
+  if (gc_fid != -1)
+    close (gc_fid);
+  shmdt (shared_memory);
+  if (sig == -1)
+  {
+    shmctl (arguments.shmid, IPC_RMID, ((struct shmid_ds *) 0));
+    if (!arguments.keep_p)
+      unlink (arguments.file_name);
+  }
+  exit (0);
+  /*NOTREACHED*/
+}
+
+static void
+DEFUN (abort_operation, (sig), int sig)
+{
+  signal (SIGQUIT, abort_operation);
+  myself->state = drone_aborting;
+  longjmp (abort_point, 1);
+  /*NOTREACHED*/
+}
+
+#if 0
+static void
+DEFUN (handle_child_death, (sig), int sig)
+{
+  signal (SIGCHLD, handle_child_death);
+  (void) (wait ((int *) 0));
+  return;
+}
+#endif
+
+static void
+DEFUN (continue_running, (sig), int sig)
+{
+  signal (SIGCONT, continue_running);
+  return;
+}
+
+static int
+DEFUN (always_one, (operation_name, noise),
+       char * operation_name AND char * noise)
+{
+  return (1);
+}
+\f
+static void
+DEFUN (process_requests, (drone), struct drone_info * drone)
+{
+  extern int EXFUN (select, (int, int *, int *, int *, struct timeval *));
+  long non_blocking_signal_mask, blocking_signal_mask, current_position = -1;
+  struct timeval timeout;
+  int result, count, buffer_index, flags;
+  pid_t read_pid;
+
+  myself = drone;
+  drone->DRONE_PID = (getpid ());
+  gc_fid = (open (arguments.file_name, O_RDWR, 0644));
+  if (gc_fid == -1)
+  {
+    fprintf (stderr,
+            "%s (%d, process_requests): open failed. errno = %s.\n",   
+            arguments.program_name, drone->index, (error_name (errno)));
+    fflush (stderr);
+    if (drone->DRONE_PPID == parent_pid)
+      (void) (kill (parent_pid, SIGCONT));
+    shutdown (0);
+    /*NOTREACHED*/
+  }
+#ifdef DEBUG_1
+  printf ("%s (%d, process_requests): Starting.\n",
+         arguments.program_name, drone->index);
+  fflush (stdout);
+#endif
+  do
+  {
+    struct stat file_info;
+    
+    /* Force O_SYNC only if we are dealing with a raw device. */
+
+    if ((fstat (gc_fid, &file_info)) == -1)
+    {
+      fprintf (stderr,
+              "%s (%d, process_requests): fstat failed. errno = %s.\n",
+              arguments.program_name, drone->index, (error_name (errno)));
+      fflush (stderr);
+    }
+    else if ((file_info.st_mode & S_IFMT) != S_IFCHR)
+      break;
+
+    if ((flags = (fcntl (gc_fid, F_GETFL, 0))) == -1)
+    {
+      fprintf
+       (stderr,
+        "%s (%d, process_requests): fcntl (F_GETFL) failed. errno = %s.\n",
+        arguments.program_name, drone->index, (error_name (errno)));
+      fflush (stderr);
+    }
+    else
+    {
+      flags |= O_SYNC;
+      if ((fcntl (gc_fid, F_SETFL, flags)) == -1)
+      {
+       fprintf
+         (stderr,
+          "%s (%d, process_requests): fcntl (F_SETFL) failed. errno = %s.\n",
+          arguments.program_name, drone->index, (error_name (errno)));
+       fflush (stderr);
+      }
+    }
+  } while (0);
+\f
+  drone->state = drone_idle;
+#ifdef DEBUG_1
+  printf ("%s (%d, process_requests): PID = %d; PPID = %d.\n",
+         arguments.program_name, drone->index, drone->DRONE_PID,
+         drone->DRONE_PPID);
+  fflush (stdout);
+#endif
+  if (drone->DRONE_PPID == parent_pid)
+    (void) (kill (parent_pid, SIGCONT));
+  count = drone->index; 
+  non_blocking_signal_mask = (sigblock (sigmask (SIGQUIT)));
+  blocking_signal_mask = (sigblock (sigmask (SIGQUIT)));
+  signal (SIGQUIT, abort_operation);
+  if (setjmp (abort_point))
+    goto redo_dispatch;
+
+  for (; 1; count++)
+  {
+    (void) (sigsetmask (non_blocking_signal_mask));
+    timeout.tv_sec = 6;
+    timeout.tv_usec = 0;
+    result = (select (0, 0, 0, 0, &timeout));
+
+    if ((result == -1) && (errno == EINTR))
+    {
+redo_dispatch:
+      switch (drone->state)
+      {
+       default:
+         fprintf (stderr,
+                  "\n%s (%d, process_requests): Unknown/bad operation %d.\n",
+                  arguments.program_name, drone->index, drone->state);
+         fflush (stderr);
+         (void) (shutdown (0));
+         /*NOTREACHED*/
+
+       case drone_idle:
+         continue;
+
+       case drone_aborting:
+#ifdef DEBUG_1
+         printf ("\n%s (%d, process_requests): Aborting.",
+                 arguments.program_name, drone->index);
+         fflush (stdout);
+#endif
+         drone->buffer_index = -1;
+         current_position = -1;
+         break;
+
+       case drone_reading:
+       case drone_writing:
+       {
+         /* Can't use buffer->bottom because the shared memory may be
+            attached at a different address!
+          */
+
+         int saved_errno;
+         char * operation_name, * buffer_address;
+         struct buffer_info * buffer;
+         struct gc_queue_entry * entry;
+
+         buffer_index = (drone->buffer_index);
+         buffer = (gc_buffers + buffer_index);
+\f
+         entry = ((struct gc_queue_entry *)
+                  (((char *) drone) + (drone->entry_offset)));
+         entry->error_code = 0;
+
+         operation_name = ((drone->state == drone_reading)
+                           ? "read"
+                           : "write");
+         buffer_address = (shared_memory + (arguments.bufsiz * buffer_index));
+#ifdef DEBUG_1
+         printf ("\n%s (%d, process_requests %s): Buffer index = %d",
+                 arguments.program_name, drone->index, operation_name,
+                 buffer_index);
+         printf ("\n\tBuffer address = 0x%lx; Position = 0x%lx; Size = 0x%lx.",
+                 buffer_address, buffer->position, buffer->size);
+         fflush (stdout);
+#endif
+
+         result = (retrying_file_operation
+                   (((drone->state == drone_reading)
+                     ? ((int (*) ()) read)
+                     : ((int (*) ()) write)),
+                    gc_fid, buffer_address,
+                    buffer->position, buffer->size, operation_name, NULL,
+                    &current_position, always_one));
+
+         saved_errno = errno;
+         (void) (sigsetmask (blocking_signal_mask));
+
+         if (result == -1)
+         {
+           buffer->state = ((drone->state == drone_reading)
+                            ? buffer_read_error
+                            : buffer_write_error);
+           drone->buffer_index = -1;
+           entry->drone_index = -1;
+           entry->error_code = saved_errno;
+           entry->state = entry_error;
+           current_position = -1;
+#ifdef DEBUG
+           printf ("\n%s (%d, process_requests): %s error (errno = %s).\n",
+                   arguments.program_name, drone->index, operation_name,
+                   (error_name (saved_errno)));
+           fflush (stdout);
+#endif
+         }
+         else
+         {
+           buffer->state = ((drone->state == drone_reading)
+                            ? buffer_ready
+                            : buffer_idle);
+           drone->buffer_index = -1;
+           entry->drone_index = -1;
+           if (drone->state == drone_writing)
+           {
+             entry->retry_count = 0;
+             entry->state = entry_idle;
+           }
+#ifdef DEBUG_1
+         printf ("\n%s (%d, process_requests %s): Done.",
+                 arguments.program_name, drone->index, operation_name);
+         fflush (stdout);
+#endif
+         }
+       }
+      }
+\f
+      drone->state = drone_idle;
+      read_pid = (*wait_pid);
+      if ((read_pid == parent_pid) || (read_pid == drone->DRONE_PID))
+       (void) (kill (parent_pid, SIGCONT));
+      count = 0;
+    }
+    else if ((result == 0) && (count == arguments.tdron))
+    {
+      count = 0;
+      if ((kill (parent_pid, 0)) == -1)
+       (void) (shutdown (-1));
+    }
+  }
+}
+
+static void
+DEFUN_VOID (start_drones)
+{
+  pid_t my_pid;
+  int counter, cpid;
+  long * drone_version;
+  struct drone_info *gc_drones, *drone;
+
+  my_pid = (getpid ());
+  shared_memory = (shmat (arguments.shmid, ATTACH_POINT, 0));
+  if (shared_memory == ((char *) -1))
+  {
+    fprintf (stderr,
+            "\
+%s (start_drones): Unable to attach shared memory segment %d (errno = %s).\n",
+            arguments.program_name, arguments.shmid, (error_name (errno)));
+    fflush (stderr);
+    exit (1);
+  }
+#ifdef DEBUG_1
+  printf ("%s (start_drones): Attached shared memory at address = 0x%lx.\n",
+         arguments.program_name, ((long) shared_memory));
+  fflush (stdout);
+#endif
+  signal (SIGINT, SIG_IGN);
+  signal (SIGQUIT, SIG_IGN);
+  signal (SIGHUP, shutdown);
+  signal (SIGTERM, shutdown);
+  signal (SIGCONT, continue_running);
+  gc_buffers = ((struct buffer_info *)
+               (shared_memory + (arguments.nbuf * arguments.bufsiz)));
+  gc_drones = ((struct drone_info *) (gc_buffers + arguments.nbuf));
+  drone_version = ((long *) (gc_drones + arguments.tdron));
+  wait_pid = ((pid_t *) (drone_version + 1));
+  if (*drone_version != DRONE_VERSION_NUMBER)
+  {
+    fprintf (stderr, "%s (start_drones): stored drone version != drone version.\n",
+            arguments.program_name);
+    fprintf (stderr, "\t*drone_version = %d; DRONE_VERSION_NUMBER = %d.\n",
+            *drone_version, DRONE_VERSION_NUMBER);
+    fflush (stderr);
+    exit (1);
+  }
+\f
+  for (counter = 1, drone = (gc_drones + (arguments.sdron + 1));
+       counter < arguments.ndron;
+       counter++, drone ++)
+  {
+    if ((cpid = (fork ())) == 0)
+    {
+      drone->DRONE_PPID = my_pid;
+      process_requests (drone);
+      /*NOTREACHED*/
+    }
+    else if (cpid == -1)
+    {
+      fprintf (stderr,
+              "%s (start_drones): fork failed; errno = %s.\n",
+              arguments.program_name, (error_name (errno)));
+      fflush (stderr);
+    }
+  }
+  drone = (gc_drones + arguments.sdron);
+  drone->DRONE_PPID = parent_pid;
+  if (arguments.ndron != 1)
+#if 0
+    signal (SIGCHLD, handle_child_death);
+#else
+    signal (SIGCHLD, SIG_IGN);
+#endif
+  process_requests (drone);
+  /*NOTREACHED*/
+}
+\f
+void
+DEFUN (main, (argc, argv), int argc AND char ** argv)
+{
+  int count, nargs;
+  static char err_buf[1024];
+#if defined(DEBUG) || defined(DEBUG_1)
+  static char out_buf[1024];
+
+  setvbuf (stdout, &out_buf[0], _IOFBF, (sizeof (out_buf)));
+#endif
+  setvbuf (stderr, &err_buf[0], _IOFBF, (sizeof (err_buf)));
+
+#ifdef DEBUG_1
+  printf ("%s (main): Arguments =\n", argv[0]);
+  for (count = 1; count < argc; count++)
+    printf ("\t%s\n", argv[count]);
+  fflush (stdout);
+#endif
+
+  nargs = ((sizeof (command_line)) / (sizeof (struct argdesc)));
+  parent_pid = (getppid ());
+  if (argc != nargs)
+  {
+    fprintf (stderr,
+            "%s (main): Wrong number of arguments (got %d, expected %d).\n",
+            argv[0], (argc - 1), (nargs - 1));
+    fflush (stderr);
+    kill (parent_pid, SIGCONT);
+    exit (1);
+  }
+  for (count = 0; count < nargs; count++)
+  {
+    if (command_line[count].format == STRING_FMT)
+      (* ((char **) command_line[count].location)) = argv[count];
+    else
+      sscanf (argv[count],
+             command_line[count].format,
+             command_line[count].location);
+  }
+
+#ifdef DEBUG_1
+  printf ("%s (main): Parsed arguments =\n", argv[0]);
+  for (count = 0; count < nargs; count++)
+  {
+    if (command_line[count].format == STRING_FMT)
+      printf ("\t%s\t= %s\n",
+             command_line[count].name,
+             (* ((char **) (command_line[count].location))));
+    else
+      printf ("\t%s\t= %d\n",
+             command_line[count].name,
+             (* ((int *) (command_line[count].location))));
+  }
+  fflush (stdout);
+#endif
+
+  start_drones ();
+  exit (0);
+}
+
+#define MAIN main
+
+#endif /* HAVE_SYSV_SHARED_MEMORY */
+\f
+#ifndef MAIN
+
+void
+DEFUN (main, (argc, argv), int argc AND char ** argv)
+{
+  fprintf (stderr, "%s: Not implemented.\n", (argv[0]));
+  fflush (stderr);
+  exit (1);
+}
+
+#endif /* MAIN */
diff --git a/v7/src/microcode/bchdrn.h b/v7/src/microcode/bchdrn.h
new file mode 100644 (file)
index 0000000..580520e
--- /dev/null
@@ -0,0 +1,181 @@
+/* -*-C-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/bchdrn.h,v 1.1 1991/10/29 22:34:20 jinx Exp $
+
+Copyright (c) 1991 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+/* Header file for overlapped I/O in bchscheme. */
+
+#ifndef _BCHDRN_H_INCLUDED
+
+#define _BCHDRN_H_INCLUDED
+
+#include "ansidecl.h"
+#ifdef _HPUX
+#  define HAVE_PREALLOC
+#  include <unistd.h>
+#endif
+#ifdef _SUNOS4
+#  include <unistd.h>
+#endif
+#ifdef _ULTRIX
+#  include <unistd.h>
+#endif
+#include <errno.h>
+
+/* #define AVOID_SYSV_SHARED_MEMORY */
+\f
+#if defined(_HPUX) && !defined(AVOID_SYSV_SHARED_MEMORY)
+#  define HAVE_SYSV_SHARED_MEMORY
+
+#  include <magic.h>
+#  if defined(SHL_MAGIC)
+#    define hpux8 1
+#  endif
+
+/* Page tables can have no gaps in HP-UX < 8.0, leave a gap for malloc. */
+
+#  ifdef hp9000s300
+#    ifdef hpux8
+#      define ATTACH_POINT     0x60000000
+#    else /* not hpux8 */
+#      define MALLOC_SPACE     (2 << 20)       /* 2 Meg */
+#    endif /* hpux8 */
+#  endif /* hp9000s300 */
+
+#endif /* _HPUX */
+
+#if defined(_SUNOS4) && !defined(AVOID_SYSV_SHARED_MEMORY)
+#  define HAVE_SYSV_SHARED_MEMORY
+#endif /* _SUNOS4 */
+
+#if defined(_ULTRIX) && !defined(AVOID_SYSV_SHARED_MEMORY)
+#  define HAVE_SYSV_SHARED_MEMORY
+#endif /* _ULTRIX */
+
+#ifdef HAVE_SYSV_SHARED_MEMORY
+
+#define DRONE_VERSION_NUMBER           ((1 << 16) | 1)
+
+#include <sys/time.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#ifndef MALLOC_SPACE
+#  define MALLOC_SPACE 0
+#endif
+
+#ifndef ATTACH_POINT
+#  define ATTACH_POINT 0
+#endif
+
+#define DRONE_EXTRA_T
+
+struct drone_extra_s
+{
+  pid_t my_pid;
+  pid_t my_ppid;
+};
+
+typedef struct drone_extra_s drone_extra_t;
+
+#define DRONE_PID      drone_extra.my_pid
+#define DRONE_PPID     drone_extra.my_ppid
+
+#endif /* HAVE_SYSV_SHARED_MEMORY */
+\f
+/* Shared definitions for all versions */
+
+enum buffer_state
+{
+  buffer_idle,                 /* 0 */
+  buffer_busy,                 /* 1, used for scan or free */
+  buffer_ready,                        /* 2, after being read */
+  buffer_queued,               /* 3, never written, use as if read */
+  buffer_being_read,           /* 4 */
+  buffer_read_error,           /* 5 */
+  buffer_being_written,                /* 6 */
+  buffer_write_error           /* 7 */
+};
+
+struct buffer_info
+{
+  int index;
+  enum buffer_state state;
+  long position;
+  long size;
+  PTR bottom;
+  PTR top;
+  PTR end;
+};
+
+enum drone_state
+{
+  drone_dead,                  /* 0 */
+  drone_not_ready,             /* 1 */
+  drone_idle,                  /* 2 */
+  drone_reading,               /* 3 */
+  drone_writing,               /* 4 */
+  drone_aborting               /* 5 */
+};
+
+struct drone_info
+{
+  int index;
+#ifdef DRONE_EXTRA_T
+  drone_extra_t drone_extra;
+#endif
+  enum drone_state state;
+  int buffer_index;
+  long entry_offset;
+};
+
+enum queue_entry_state
+{
+  entry_idle,                  /* 0 */
+  entry_busy,                  /* 1 */
+  entry_error                  /* 2 */
+};
+
+struct gc_queue_entry
+{
+  int index;
+  enum queue_entry_state state;
+  struct buffer_info * buffer;
+  int drone_index;
+  int error_code;
+  int retry_count;
+};
+
+#endif /* _BCHDRN_H_INCLUDED */
diff --git a/v7/src/microcode/bchutl.c b/v7/src/microcode/bchutl.c
new file mode 100644 (file)
index 0000000..d134d58
--- /dev/null
@@ -0,0 +1,107 @@
+/* -*-C-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/bchutl.c,v 1.1 1991/10/29 22:35:01 jinx Exp $
+
+Copyright (c) 1991 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+#include <errno.h>
+#include <unistd.h>
+#include "ansidecl.h"
+
+extern char * EXFUN (error_name, (int));
+extern int EXFUN (retrying_file_operation,
+                 (int (*)(int, char *, unsigned int),
+                  int, char *, long, long, char *, char *, long *,
+                  int (*)(char *, char *)));
+\f
+char *
+DEFUN (error_name, (code), int code)
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  static char buf[512];
+
+  if ((code >= 0) && (code <= sys_nerr))
+    sprintf (&buf[0], "%d, %s", code, sys_errlist[code]);
+  else
+    sprintf (&buf[0], "%d, unknown error", code);
+  return (&buf[0]);
+}
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+int
+DEFUN (retrying_file_operation,
+       (operation, fid, ptr, position, nbytes, name, noise, curpos, abort_p),
+       int EXFUN ((*operation), (int, char *, unsigned int))
+       AND int fid AND char * ptr AND long position AND long nbytes
+       AND char * name AND char * noise AND long * curpos
+       AND int EXFUN ((*abort_p), (char *, char *)))
+{
+  char * membuf = ptr;
+  long
+    bytes_to_transfer = nbytes,
+    bytes_transferred;
+
+  if (*curpos != position)
+    while ((lseek (fid, position, SEEK_SET)) == -1)
+      if ((errno != EINTR) && ((*abort_p) ("lseek", noise)))
+       goto fail;
+
+  while ((bytes_to_transfer > 0)
+        && ((bytes_transferred =
+             ((*operation) (fid, membuf, ((unsigned int) bytes_to_transfer))))
+            != bytes_to_transfer))
+    if (bytes_transferred == -1)
+    {
+      if ((errno != EINTR) && ((*abort_p) (name, noise)))
+       goto fail;
+
+      while ((lseek (fid, (position + (nbytes - bytes_to_transfer)), SEEK_SET))
+            == -1)
+       if ((errno != EINTR) && ((*abort_p) ("lseek", noise)))
+         goto fail;
+    }
+    else
+    {
+      bytes_to_transfer -= bytes_transferred;
+      membuf += bytes_transferred;
+    }
+  *curpos = (position + nbytes);
+  return (nbytes);
+
+fail:
+  *curpos = -1;
+  return (-1);
+}
+