xref: /csrg-svn/usr.sbin/rmt/rmt.c (revision 61871)
121175Sdist /*
2*61871Sbostic  * Copyright (c) 1983, 1993
3*61871Sbostic  *	The Regents of the University of California.  All rights reserved.
434852Sbostic  *
542818Sbostic  * %sccs.include.redist.c%
621175Sdist  */
721175Sdist 
86448Swnj #ifndef lint
9*61871Sbostic static char copyright[] =
10*61871Sbostic "@(#) Copyright (c) 1983, 1993\n\
11*61871Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1234852Sbostic #endif /* not lint */
136448Swnj 
1421175Sdist #ifndef lint
15*61871Sbostic static char sccsid[] = "@(#)rmt.c	8.1 (Berkeley) 06/06/93";
1634852Sbostic #endif /* not lint */
1721175Sdist 
186448Swnj /*
196448Swnj  * rmt
206448Swnj  */
216448Swnj #include <sys/types.h>
2217537Sralph #include <sys/socket.h>
236448Swnj #include <sys/mtio.h>
246448Swnj #include <errno.h>
2560117Storek #include <fcntl.h>
2660117Storek #include <sgtty.h>
2760117Storek #include <stdio.h>
2860117Storek #include <stdlib.h>
2942391Sbostic #include <string.h>
3060117Storek #include <unistd.h>
316448Swnj 
326448Swnj int	tape = -1;
336448Swnj 
3418475Smckusick char	*record;
3518475Smckusick int	maxrecsize = -1;
366448Swnj 
376448Swnj #define	SSIZE	64
386448Swnj char	device[SSIZE];
396448Swnj char	count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE];
406448Swnj 
416448Swnj char	resp[BUFSIZ];
426448Swnj 
436448Swnj FILE	*debug;
4417370Ssam #define	DEBUG(f)	if (debug) fprintf(debug, f)
4517370Ssam #define	DEBUG1(f,a)	if (debug) fprintf(debug, f, a)
4617370Ssam #define	DEBUG2(f,a1,a2)	if (debug) fprintf(debug, f, a1, a2)
476448Swnj 
4860117Storek char	*checkbuf __P((char *, int));
4960117Storek void	 error __P((int));
5060117Storek void	 getstring __P((char *));
5160117Storek 
5260117Storek int
main(argc,argv)536448Swnj main(argc, argv)
546448Swnj 	int argc;
556448Swnj 	char **argv;
566448Swnj {
576560Smckusick 	int rval;
586448Swnj 	char c;
596448Swnj 	int n, i, cc;
606448Swnj 
616448Swnj 	argc--, argv++;
626448Swnj 	if (argc > 0) {
636448Swnj 		debug = fopen(*argv, "w");
646448Swnj 		if (debug == 0)
656448Swnj 			exit(1);
6660117Storek 		(void)setbuf(debug, (char *)0);
676448Swnj 	}
686448Swnj top:
696448Swnj 	errno = 0;
706448Swnj 	rval = 0;
716448Swnj 	if (read(0, &c, 1) != 1)
726448Swnj 		exit(0);
736448Swnj 	switch (c) {
746448Swnj 
756448Swnj 	case 'O':
766448Swnj 		if (tape >= 0)
776448Swnj 			(void) close(tape);
7860117Storek 		getstring(device);
7960117Storek 		getstring(mode);
8017370Ssam 		DEBUG2("rmtd: O %s %s\n", device, mode);
816448Swnj 		tape = open(device, atoi(mode));
826448Swnj 		if (tape < 0)
836448Swnj 			goto ioerror;
846841Smckusick 		goto respond;
856448Swnj 
866448Swnj 	case 'C':
8717370Ssam 		DEBUG("rmtd: C\n");
8817370Ssam 		getstring(device);		/* discard */
896448Swnj 		if (close(tape) < 0)
906448Swnj 			goto ioerror;
916448Swnj 		tape = -1;
926841Smckusick 		goto respond;
936448Swnj 
946448Swnj 	case 'L':
9560117Storek 		getstring(count);
9660117Storek 		getstring(pos);
9717370Ssam 		DEBUG2("rmtd: L %s %s\n", count, pos);
9860137Sbostic 		rval = lseek(tape, (off_t)atol(count), atoi(pos));
996448Swnj 		if (rval < 0)
1006448Swnj 			goto ioerror;
1016841Smckusick 		goto respond;
1026448Swnj 
1036448Swnj 	case 'W':
10417370Ssam 		getstring(count);
1056448Swnj 		n = atoi(count);
10617370Ssam 		DEBUG1("rmtd: W %s\n", count);
10718475Smckusick 		record = checkbuf(record, n);
1086448Swnj 		for (i = 0; i < n; i += cc) {
1096448Swnj 			cc = read(0, &record[i], n - i);
1106448Swnj 			if (cc <= 0) {
11117370Ssam 				DEBUG("rmtd: premature eof\n");
11218475Smckusick 				exit(2);
1136448Swnj 			}
1146448Swnj 		}
1156448Swnj 		rval = write(tape, record, n);
1166448Swnj 		if (rval < 0)
1176448Swnj 			goto ioerror;
1186841Smckusick 		goto respond;
1196448Swnj 
1206448Swnj 	case 'R':
12117370Ssam 		getstring(count);
12217370Ssam 		DEBUG1("rmtd: R %s\n", count);
1236448Swnj 		n = atoi(count);
12418475Smckusick 		record = checkbuf(record, n);
1256448Swnj 		rval = read(tape, record, n);
1266448Swnj 		if (rval < 0)
1276448Swnj 			goto ioerror;
12860117Storek 		(void)sprintf(resp, "A%d\n", rval);
12960117Storek 		(void)write(1, resp, strlen(resp));
13060117Storek 		(void)write(1, record, rval);
1316841Smckusick 		goto top;
1326448Swnj 
1336448Swnj 	case 'I':
13460117Storek 		getstring(op);
13560117Storek 		getstring(count);
13617370Ssam 		DEBUG2("rmtd: I %s %s\n", op, count);
1376448Swnj 		{ struct mtop mtop;
1386448Swnj 		  mtop.mt_op = atoi(op);
1396448Swnj 		  mtop.mt_count = atoi(count);
1406448Swnj 		  if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0)
1416448Swnj 			goto ioerror;
1426448Swnj 		  rval = mtop.mt_count;
1436448Swnj 		}
1446841Smckusick 		goto respond;
1456448Swnj 
1466448Swnj 	case 'S':		/* status */
14717370Ssam 		DEBUG("rmtd: S\n");
1486448Swnj 		{ struct mtget mtget;
1496448Swnj 		  if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0)
1506448Swnj 			goto ioerror;
1516448Swnj 		  rval = sizeof (mtget);
15260117Storek 		  (void)sprintf(resp, "A%d\n", rval);
15360117Storek 		  (void)write(1, resp, strlen(resp));
15460117Storek 		  (void)write(1, (char *)&mtget, sizeof (mtget));
15517854Sralph 		  goto top;
1566448Swnj 		}
1576448Swnj 
1586448Swnj 	default:
15917370Ssam 		DEBUG1("rmtd: garbage command %c\n", c);
16018475Smckusick 		exit(3);
1616448Swnj 	}
1626841Smckusick respond:
16317370Ssam 	DEBUG1("rmtd: A %d\n", rval);
16460117Storek 	(void)sprintf(resp, "A%d\n", rval);
16560117Storek 	(void)write(1, resp, strlen(resp));
1666448Swnj 	goto top;
1676448Swnj ioerror:
1686448Swnj 	error(errno);
1696448Swnj 	goto top;
1706448Swnj }
1716448Swnj 
17260117Storek void
getstring(bp)17317370Ssam getstring(bp)
1746448Swnj 	char *bp;
1756448Swnj {
1766448Swnj 	int i;
1776448Swnj 	char *cp = bp;
1786448Swnj 
1796448Swnj 	for (i = 0; i < SSIZE; i++) {
1806448Swnj 		if (read(0, cp+i, 1) != 1)
1816448Swnj 			exit(0);
1826448Swnj 		if (cp[i] == '\n')
1836448Swnj 			break;
1846448Swnj 	}
1856448Swnj 	cp[i] = '\0';
1866448Swnj }
1876448Swnj 
18818475Smckusick char *
checkbuf(record,size)18918475Smckusick checkbuf(record, size)
19018475Smckusick 	char *record;
19118475Smckusick 	int size;
19218475Smckusick {
19318475Smckusick 
19418475Smckusick 	if (size <= maxrecsize)
19518475Smckusick 		return (record);
19618475Smckusick 	if (record != 0)
19718475Smckusick 		free(record);
19818475Smckusick 	record = malloc(size);
19918475Smckusick 	if (record == 0) {
20018475Smckusick 		DEBUG("rmtd: cannot allocate buffer space\n");
20118475Smckusick 		exit(4);
20218475Smckusick 	}
20325714Smckusick 	maxrecsize = size;
20418498Smckusick 	while (size > 1024 &&
20518498Smckusick 	       setsockopt(0, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0)
20618498Smckusick 		size -= 1024;
20718475Smckusick 	return (record);
20818475Smckusick }
20918475Smckusick 
21060117Storek void
error(num)2116448Swnj error(num)
2126448Swnj 	int num;
2136448Swnj {
2146448Swnj 
21542391Sbostic 	DEBUG2("rmtd: E %d (%s)\n", num, strerror(num));
21660117Storek 	(void)sprintf(resp, "E%d\n%s\n", num, strerror(num));
21760117Storek 	(void)write(1, resp, strlen(resp));
2186448Swnj }
219