home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume22
/
ftape
/
part01
/
ftaperead.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-04
|
6KB
|
211 lines
#ifndef lint
static char sccs_id[] = "@(#)2.4 ftaperead.c 91/09/03 FAST TAPE";
#endif
/*
* Original author: Kari Yli-Kuha, SQ Consulting Ltd.
* Address: Kanslerinkatu 8, 33720 Tampere, Finland
* Phone: (358) 31 165200
*
* Reads tape blocks to shared memory buffers.
*
* Handles tape changing if we're attached to terminal, otherwise exits.
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include "ftape.h"
extern void perror(), exit();
extern char *strrchr();
extern int errno;
extern struct SHBUF *shbuf; /* shared memory */
static struct SHBUF *buf; /* current buffer */
static int nbuf = 0; /* buffer counter */
static void quit(); /* signal catching */
static char *progname; /* name of this program */
/*
* main
*/
main(argc, argv)
int argc;
char *argv[];
{
extern int optind; /* option index */
extern char *optarg; /* option's argument */
int opt; /* current option */
char *tape_device = TAPE; /* default tape device */
int shbufs = SHBUFS; /* default # of buffers */
int debug = 0; /* default: nodebug mode */
int fdtape; /* tape file desciptor */
int end = 0; /* flag to stop reading */
FILE * ttyin, *ttyout; /* terminal (if any) */
char *cp; /* local pointer */
int n; /* local counter */
progname = ((cp = strrchr (argv[0], '/')) ? cp+1 : argv[0]);
/*
* options
*/
while ( (opt = getopt(argc, argv, "dn:f:")) != EOF ) {
switch (opt) {
case 'n': /* # of buffers */
shbufs = atoi(optarg);
if (shbufs <= 0) {
(void) fprintf (stderr, "%s: too few buffers: %d\n", progname, shbufs);
exit(1);
}
break;
case 'f':
tape_device = optarg;
break;
case 'd':
debug++;
break;
default: /* unknown option */
(void) fprintf (stderr, "%s: unknown option -- %c\n", progname, opt);
exit(1);
break;
}
}
/* catch signals */
for (n = 0; n < NSIG; n++)
(void) signal (n, quit);
/*
* Try to attach to terminal if possible.
* It may not be possible if we're running in background
* or started by 'cron'. In that case tty{in,out} == NULL
*/
ttyin = fopen ("/dev/tty", "r");
ttyout = fopen ("/dev/tty", "w");
/* shared memory should already be created - attach to it */
if (attach_shared(tape_device) == -1)
exit (1);
if ((fdtape = open(tape_device, O_RDONLY)) == -1) {
(void) fprintf (stderr, "%s: cannot open tape, errno %d\n"
, progname, errno);
exit (1);
}
/* READING LOOP */
nbuf = 0;
buf = shbuf;
end = 0;
while (!end) {
semdown (BUFFERS_FREE, 1);
errno = 0; /* clear errno, read doesn't do it */
buf->nread = read (fdtape, buf->buf, SHBUFSIZE*512);
switch (buf->nread) {
case 0: /* end of archive */
DEBUG fprintf (ttyout, "\n%s: READ %d bytes, errno %d\n",
progname, buf->nread, errno);
semup (BUFFERS_AVAIL, 1);
end = 1;
break;
case -1: /* End Of Media with no data */
DEBUG fprintf (ttyout, "\n%s: READ %d bytes, errno %d\n",
progname, buf->nread, errno);
(void) close(fdtape);
/*
* If we're attached to a terminal ask user to change the tape.
* otherwise exit.
*/
if (ttyin && ttyout)
fdtape = change_tape(ttyin, ttyout, tape_device);
else {
(void) fprintf (stderr, "Reached end of medium.\n");
(void) fprintf (stderr, "No controlling terminal. Exit.\n");
quit(-1);
}
break; /* continue reading to the same buffer */
case SHBUFSIZE*512: /* OK, buffer read */
default: /*
* EOM or smaller buffer at end of archive (EOA).
* We simply pass the data on and check it during the
* next read cycle.
* If we're at EOA, next read should give "0" bytes.
* If we're at EOM, next read should give "-1" bytes
*/
DEBUG fprintf (ttyout, "%s: READ %d bytes, errno %d \r",
progname, buf->nread, errno), fflush(ttyout);
semup (BUFFERS_AVAIL, 1);
/* next buffer */
nbuf++; buf++;
if (nbuf >= shbufs) {
nbuf = 0;
buf = shbuf;
}
break;
}
}
return (0);
}
/*
* quit is called either by a signal interrupt (sig > 0) or
* explicitly (sig < 0).
*
* Signal interrupt is written to stderr
*/
static void quit (sig)
int sig;
{
if (sig > 0)
fprintf (stderr, "%s: exit signal %d\n", progname, sig);
buf->nread = 0;
semup (BUFFERS_AVAIL, 1);
exit (1);
}
/*
* change_tape
*/
change_tape(ttyin, ttyout, device)
FILE *ttyin, *ttyout;
char *device;
{
static char inbuf[BUFSIZ];
int (fdtape);
(void) fprintf (ttyout, "\nReached end of medium.\n");
(void) fprintf (ttyout, "Change tape after the light is off.\n");
while (1) {
(void) fprintf (ttyout, "Press 'y' <RETURN> to continue: ");
fgets (inbuf, sizeof(inbuf), ttyin); /* read tty */
if (tolower(inbuf[0]) != 'y') {
(void) fprintf (ttyout, "\007"); /* BEEP - illegal reply */
continue;
}
if ((fdtape = open(device, O_RDONLY)) != -1)
break; /* succeeded opening tape */
(void) fprintf (ttyout, "\007Could not open tape for reading.\n");
(void) fprintf (ttyout, "Check if it's properly installed.\n");
continue;
}
return fdtape;
}