--- /dev/null
+/* -*- 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,
+ ¤t_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 */
--- /dev/null
+/* -*-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 */
--- /dev/null
+/* -*-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);
+}
+