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