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