xref: /csrg-svn/usr.sbin/rmt/rmt.c (revision 42391)
121175Sdist /*
221175Sdist  * Copyright (c) 1983 Regents of the University of California.
334852Sbostic  * All rights reserved.
434852Sbostic  *
534852Sbostic  * Redistribution and use in source and binary forms are permitted
634852Sbostic  * provided that the above copyright notice and this paragraph are
734852Sbostic  * duplicated in all such forms and that any documentation,
834852Sbostic  * advertising materials, and other materials related to such
934852Sbostic  * distribution and use acknowledge that the software was developed
1034852Sbostic  * by the University of California, Berkeley.  The name of the
1134852Sbostic  * University may not be used to endorse or promote products derived
1234852Sbostic  * from this software without specific prior written permission.
1334852Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434852Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534852Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621175Sdist  */
1721175Sdist 
186448Swnj #ifndef lint
1921175Sdist char copyright[] =
2021175Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
2121175Sdist  All rights reserved.\n";
2234852Sbostic #endif /* not lint */
236448Swnj 
2421175Sdist #ifndef lint
25*42391Sbostic static char sccsid[] = "@(#)rmt.c	5.5 (Berkeley) 05/27/90";
2634852Sbostic #endif /* not lint */
2721175Sdist 
286448Swnj /*
296448Swnj  * rmt
306448Swnj  */
316448Swnj #include <stdio.h>
326448Swnj #include <sgtty.h>
336448Swnj #include <sys/types.h>
3417537Sralph #include <sys/socket.h>
356448Swnj #include <sys/mtio.h>
366448Swnj #include <errno.h>
37*42391Sbostic #include <string.h>
386448Swnj 
396448Swnj int	tape = -1;
406448Swnj 
4118475Smckusick char	*record;
4218475Smckusick int	maxrecsize = -1;
4318475Smckusick char	*checkbuf();
446448Swnj 
456448Swnj #define	SSIZE	64
466448Swnj char	device[SSIZE];
476448Swnj char	count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE];
486448Swnj 
496448Swnj char	resp[BUFSIZ];
506448Swnj 
516448Swnj long	lseek();
526448Swnj 
536448Swnj FILE	*debug;
5417370Ssam #define	DEBUG(f)	if (debug) fprintf(debug, f)
5517370Ssam #define	DEBUG1(f,a)	if (debug) fprintf(debug, f, a)
5617370Ssam #define	DEBUG2(f,a1,a2)	if (debug) fprintf(debug, f, a1, a2)
576448Swnj 
586448Swnj main(argc, argv)
596448Swnj 	int argc;
606448Swnj 	char **argv;
616448Swnj {
626560Smckusick 	int rval;
636448Swnj 	char c;
646448Swnj 	int n, i, cc;
656448Swnj 
666448Swnj 	argc--, argv++;
676448Swnj 	if (argc > 0) {
686448Swnj 		debug = fopen(*argv, "w");
696448Swnj 		if (debug == 0)
706448Swnj 			exit(1);
716448Swnj 		(void) setbuf(debug, (char *)0);
726448Swnj 	}
736448Swnj top:
746448Swnj 	errno = 0;
756448Swnj 	rval = 0;
766448Swnj 	if (read(0, &c, 1) != 1)
776448Swnj 		exit(0);
786448Swnj 	switch (c) {
796448Swnj 
806448Swnj 	case 'O':
816448Swnj 		if (tape >= 0)
826448Swnj 			(void) close(tape);
8317370Ssam 		getstring(device); getstring(mode);
8417370Ssam 		DEBUG2("rmtd: O %s %s\n", device, mode);
856448Swnj 		tape = open(device, atoi(mode));
866448Swnj 		if (tape < 0)
876448Swnj 			goto ioerror;
886841Smckusick 		goto respond;
896448Swnj 
906448Swnj 	case 'C':
9117370Ssam 		DEBUG("rmtd: C\n");
9217370Ssam 		getstring(device);		/* discard */
936448Swnj 		if (close(tape) < 0)
946448Swnj 			goto ioerror;
956448Swnj 		tape = -1;
966841Smckusick 		goto respond;
976448Swnj 
986448Swnj 	case 'L':
9917370Ssam 		getstring(count); getstring(pos);
10017370Ssam 		DEBUG2("rmtd: L %s %s\n", count, pos);
1016448Swnj 		rval = lseek(tape, (long) atoi(count), atoi(pos));
1026448Swnj 		if (rval < 0)
1036448Swnj 			goto ioerror;
1046841Smckusick 		goto respond;
1056448Swnj 
1066448Swnj 	case 'W':
10717370Ssam 		getstring(count);
1086448Swnj 		n = atoi(count);
10917370Ssam 		DEBUG1("rmtd: W %s\n", count);
11018475Smckusick 		record = checkbuf(record, n);
1116448Swnj 		for (i = 0; i < n; i += cc) {
1126448Swnj 			cc = read(0, &record[i], n - i);
1136448Swnj 			if (cc <= 0) {
11417370Ssam 				DEBUG("rmtd: premature eof\n");
11518475Smckusick 				exit(2);
1166448Swnj 			}
1176448Swnj 		}
1186448Swnj 		rval = write(tape, record, n);
1196448Swnj 		if (rval < 0)
1206448Swnj 			goto ioerror;
1216841Smckusick 		goto respond;
1226448Swnj 
1236448Swnj 	case 'R':
12417370Ssam 		getstring(count);
12517370Ssam 		DEBUG1("rmtd: R %s\n", count);
1266448Swnj 		n = atoi(count);
12718475Smckusick 		record = checkbuf(record, n);
1286448Swnj 		rval = read(tape, record, n);
1296448Swnj 		if (rval < 0)
1306448Swnj 			goto ioerror;
1316841Smckusick 		(void) sprintf(resp, "A%d\n", rval);
1326841Smckusick 		(void) write(1, resp, strlen(resp));
1336841Smckusick 		(void) write(1, record, rval);
1346841Smckusick 		goto top;
1356448Swnj 
1366448Swnj 	case 'I':
13717370Ssam 		getstring(op); getstring(count);
13817370Ssam 		DEBUG2("rmtd: I %s %s\n", op, count);
1396448Swnj 		{ struct mtop mtop;
1406448Swnj 		  mtop.mt_op = atoi(op);
1416448Swnj 		  mtop.mt_count = atoi(count);
1426448Swnj 		  if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0)
1436448Swnj 			goto ioerror;
1446448Swnj 		  rval = mtop.mt_count;
1456448Swnj 		}
1466841Smckusick 		goto respond;
1476448Swnj 
1486448Swnj 	case 'S':		/* status */
14917370Ssam 		DEBUG("rmtd: S\n");
1506448Swnj 		{ struct mtget mtget;
1516448Swnj 		  if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0)
1526448Swnj 			goto ioerror;
1536448Swnj 		  rval = sizeof (mtget);
15417854Sralph 		  (void) sprintf(resp, "A%d\n", rval);
15517854Sralph 		  (void) write(1, resp, strlen(resp));
1566448Swnj 		  (void) write(1, (char *)&mtget, sizeof (mtget));
15717854Sralph 		  goto top;
1586448Swnj 		}
1596448Swnj 
1606448Swnj 	default:
16117370Ssam 		DEBUG1("rmtd: garbage command %c\n", c);
16218475Smckusick 		exit(3);
1636448Swnj 	}
1646841Smckusick respond:
16517370Ssam 	DEBUG1("rmtd: A %d\n", rval);
1666448Swnj 	(void) sprintf(resp, "A%d\n", rval);
1676448Swnj 	(void) write(1, resp, strlen(resp));
1686448Swnj 	goto top;
1696448Swnj ioerror:
1706448Swnj 	error(errno);
1716448Swnj 	goto top;
1726448Swnj }
1736448Swnj 
17417370Ssam getstring(bp)
1756448Swnj 	char *bp;
1766448Swnj {
1776448Swnj 	int i;
1786448Swnj 	char *cp = bp;
1796448Swnj 
1806448Swnj 	for (i = 0; i < SSIZE; i++) {
1816448Swnj 		if (read(0, cp+i, 1) != 1)
1826448Swnj 			exit(0);
1836448Swnj 		if (cp[i] == '\n')
1846448Swnj 			break;
1856448Swnj 	}
1866448Swnj 	cp[i] = '\0';
1876448Swnj }
1886448Swnj 
18918475Smckusick char *
19018475Smckusick checkbuf(record, size)
19118475Smckusick 	char *record;
19218475Smckusick 	int size;
19318475Smckusick {
19418475Smckusick 	extern char *malloc();
19518475Smckusick 
19618475Smckusick 	if (size <= maxrecsize)
19718475Smckusick 		return (record);
19818475Smckusick 	if (record != 0)
19918475Smckusick 		free(record);
20018475Smckusick 	record = malloc(size);
20118475Smckusick 	if (record == 0) {
20218475Smckusick 		DEBUG("rmtd: cannot allocate buffer space\n");
20318475Smckusick 		exit(4);
20418475Smckusick 	}
20525714Smckusick 	maxrecsize = size;
20618498Smckusick 	while (size > 1024 &&
20718498Smckusick 	       setsockopt(0, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0)
20818498Smckusick 		size -= 1024;
20918475Smckusick 	return (record);
21018475Smckusick }
21118475Smckusick 
2126448Swnj error(num)
2136448Swnj 	int num;
2146448Swnj {
2156448Swnj 
216*42391Sbostic 	DEBUG2("rmtd: E %d (%s)\n", num, strerror(num));
217*42391Sbostic 	(void) sprintf(resp, "E%d\n%s\n", num, strerror(num));
218*42391Sbostic 	(void) write(1, resp, strlen(resp));
2196448Swnj }
220