rmt.c revision 80381
11553Srgrimes/* 21553Srgrimes * Copyright (c) 1983, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 341553Srgrimes#ifndef lint 3530374Scharnierstatic const char copyright[] = 361553Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 371553Srgrimes The Regents of the University of California. All rights reserved.\n"; 381553Srgrimes#endif /* not lint */ 391553Srgrimes 401553Srgrimes#ifndef lint 4130374Scharnier#if 0 421553Srgrimesstatic char sccsid[] = "@(#)rmt.c 8.1 (Berkeley) 6/6/93"; 4330374Scharnier#endif 4430374Scharnierstatic const char rcsid[] = 4550479Speter "$FreeBSD: head/usr.sbin/rmt/rmt.c 80381 2001-07-26 11:02:39Z sheldonh $"; 461553Srgrimes#endif /* not lint */ 471553Srgrimes 481553Srgrimes/* 491553Srgrimes * rmt 501553Srgrimes */ 511553Srgrimes#include <sys/types.h> 521553Srgrimes#include <sys/socket.h> 531553Srgrimes#include <sys/mtio.h> 541553Srgrimes#include <errno.h> 551553Srgrimes#include <fcntl.h> 561553Srgrimes#include <sgtty.h> 571553Srgrimes#include <stdio.h> 581553Srgrimes#include <stdlib.h> 591553Srgrimes#include <string.h> 601553Srgrimes#include <unistd.h> 611553Srgrimes 621553Srgrimesint tape = -1; 631553Srgrimes 641553Srgrimeschar *record; 651553Srgrimesint maxrecsize = -1; 661553Srgrimes 671553Srgrimes#define SSIZE 64 681553Srgrimeschar device[SSIZE]; 691553Srgrimeschar count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE]; 701553Srgrimes 711553Srgrimeschar resp[BUFSIZ]; 721553Srgrimes 731553SrgrimesFILE *debug; 741553Srgrimes#define DEBUG(f) if (debug) fprintf(debug, f) 751553Srgrimes#define DEBUG1(f,a) if (debug) fprintf(debug, f, a) 761553Srgrimes#define DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2) 771553Srgrimes 781553Srgrimeschar *checkbuf __P((char *, int)); 791553Srgrimesvoid error __P((int)); 801553Srgrimesvoid getstring __P((char *)); 811553Srgrimes 821553Srgrimesint 831553Srgrimesmain(argc, argv) 841553Srgrimes int argc; 851553Srgrimes char **argv; 861553Srgrimes{ 871553Srgrimes int rval; 881553Srgrimes char c; 891553Srgrimes int n, i, cc; 901553Srgrimes 911553Srgrimes argc--, argv++; 921553Srgrimes if (argc > 0) { 931553Srgrimes debug = fopen(*argv, "w"); 941553Srgrimes if (debug == 0) 951553Srgrimes exit(1); 961553Srgrimes (void)setbuf(debug, (char *)0); 971553Srgrimes } 981553Srgrimestop: 991553Srgrimes errno = 0; 1001553Srgrimes rval = 0; 10180381Ssheldonh if (read(STDIN_FILENO, &c, 1) != 1) 1021553Srgrimes exit(0); 1031553Srgrimes switch (c) { 1041553Srgrimes 1051553Srgrimes case 'O': 1061553Srgrimes if (tape >= 0) 1071553Srgrimes (void) close(tape); 1081553Srgrimes getstring(device); 1091553Srgrimes getstring(mode); 1101553Srgrimes DEBUG2("rmtd: O %s %s\n", device, mode); 1117707Sjoerg /* 1127707Sjoerg * XXX the rmt protocol does not provide a means to 1137707Sjoerg * specify the permission bits; allow rw for everyone, 1147707Sjoerg * as modified by the users umask 1157707Sjoerg */ 1167707Sjoerg tape = open(device, atoi(mode), 0666); 1171553Srgrimes if (tape < 0) 1181553Srgrimes goto ioerror; 1191553Srgrimes goto respond; 1201553Srgrimes 1211553Srgrimes case 'C': 1221553Srgrimes DEBUG("rmtd: C\n"); 1231553Srgrimes getstring(device); /* discard */ 1241553Srgrimes if (close(tape) < 0) 1251553Srgrimes goto ioerror; 1261553Srgrimes tape = -1; 1271553Srgrimes goto respond; 1281553Srgrimes 1291553Srgrimes case 'L': 1301553Srgrimes getstring(count); 1311553Srgrimes getstring(pos); 1321553Srgrimes DEBUG2("rmtd: L %s %s\n", count, pos); 1331553Srgrimes rval = lseek(tape, (off_t)atol(count), atoi(pos)); 1341553Srgrimes if (rval < 0) 1351553Srgrimes goto ioerror; 1361553Srgrimes goto respond; 1371553Srgrimes 1381553Srgrimes case 'W': 1391553Srgrimes getstring(count); 1401553Srgrimes n = atoi(count); 1411553Srgrimes DEBUG1("rmtd: W %s\n", count); 1421553Srgrimes record = checkbuf(record, n); 1431553Srgrimes for (i = 0; i < n; i += cc) { 14480381Ssheldonh cc = read(STDIN_FILENO, &record[i], n - i); 1451553Srgrimes if (cc <= 0) { 1461553Srgrimes DEBUG("rmtd: premature eof\n"); 1471553Srgrimes exit(2); 1481553Srgrimes } 1491553Srgrimes } 1501553Srgrimes rval = write(tape, record, n); 1511553Srgrimes if (rval < 0) 1521553Srgrimes goto ioerror; 1531553Srgrimes goto respond; 1541553Srgrimes 1551553Srgrimes case 'R': 1561553Srgrimes getstring(count); 1571553Srgrimes DEBUG1("rmtd: R %s\n", count); 1581553Srgrimes n = atoi(count); 1591553Srgrimes record = checkbuf(record, n); 1601553Srgrimes rval = read(tape, record, n); 1611553Srgrimes if (rval < 0) 1621553Srgrimes goto ioerror; 1631553Srgrimes (void)sprintf(resp, "A%d\n", rval); 16480381Ssheldonh (void)write(STDOUT_FILENO, resp, strlen(resp)); 16580381Ssheldonh (void)write(STDOUT_FILENO, record, rval); 1661553Srgrimes goto top; 1671553Srgrimes 1681553Srgrimes case 'I': 1691553Srgrimes getstring(op); 1701553Srgrimes getstring(count); 1711553Srgrimes DEBUG2("rmtd: I %s %s\n", op, count); 1721553Srgrimes { struct mtop mtop; 1731553Srgrimes mtop.mt_op = atoi(op); 1741553Srgrimes mtop.mt_count = atoi(count); 1751553Srgrimes if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0) 1761553Srgrimes goto ioerror; 1771553Srgrimes rval = mtop.mt_count; 1781553Srgrimes } 1791553Srgrimes goto respond; 1801553Srgrimes 1811553Srgrimes case 'S': /* status */ 1821553Srgrimes DEBUG("rmtd: S\n"); 1831553Srgrimes { struct mtget mtget; 1841553Srgrimes if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0) 1851553Srgrimes goto ioerror; 1861553Srgrimes rval = sizeof (mtget); 18757155Smjacob if (rval > 24) /* original mtget structure size */ 18857155Smjacob rval = 24; 1891553Srgrimes (void)sprintf(resp, "A%d\n", rval); 19080381Ssheldonh (void)write(STDOUT_FILENO, resp, strlen(resp)); 19180381Ssheldonh (void)write(STDOUT_FILENO, (char *)&mtget, rval); 1921553Srgrimes goto top; 1931553Srgrimes } 1941553Srgrimes 19539264Sgibbs case 'V': /* version */ 19639264Sgibbs getstring(op); 19739264Sgibbs DEBUG1("rmtd: V %s\n", op); 19839264Sgibbs rval = 2; 19939264Sgibbs goto respond; 20039264Sgibbs 2011553Srgrimes default: 2021553Srgrimes DEBUG1("rmtd: garbage command %c\n", c); 2031553Srgrimes exit(3); 2041553Srgrimes } 2051553Srgrimesrespond: 2061553Srgrimes DEBUG1("rmtd: A %d\n", rval); 2071553Srgrimes (void)sprintf(resp, "A%d\n", rval); 20880381Ssheldonh (void)write(STDOUT_FILENO, resp, strlen(resp)); 2091553Srgrimes goto top; 2101553Srgrimesioerror: 2111553Srgrimes error(errno); 2121553Srgrimes goto top; 2131553Srgrimes} 2141553Srgrimes 2151553Srgrimesvoid 2161553Srgrimesgetstring(bp) 2171553Srgrimes char *bp; 2181553Srgrimes{ 2191553Srgrimes int i; 2201553Srgrimes char *cp = bp; 2211553Srgrimes 2221553Srgrimes for (i = 0; i < SSIZE; i++) { 22380381Ssheldonh if (read(STDIN_FILENO, cp+i, 1) != 1) 2241553Srgrimes exit(0); 2251553Srgrimes if (cp[i] == '\n') 2261553Srgrimes break; 2271553Srgrimes } 2281553Srgrimes cp[i] = '\0'; 2291553Srgrimes} 2301553Srgrimes 2311553Srgrimeschar * 2321553Srgrimescheckbuf(record, size) 2331553Srgrimes char *record; 2341553Srgrimes int size; 2351553Srgrimes{ 2361553Srgrimes 2371553Srgrimes if (size <= maxrecsize) 2381553Srgrimes return (record); 2391553Srgrimes if (record != 0) 2401553Srgrimes free(record); 2411553Srgrimes record = malloc(size); 2421553Srgrimes if (record == 0) { 2431553Srgrimes DEBUG("rmtd: cannot allocate buffer space\n"); 2441553Srgrimes exit(4); 2451553Srgrimes } 2461553Srgrimes maxrecsize = size; 2471553Srgrimes while (size > 1024 && 2481553Srgrimes setsockopt(0, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0) 2491553Srgrimes size -= 1024; 2501553Srgrimes return (record); 2511553Srgrimes} 2521553Srgrimes 2531553Srgrimesvoid 2541553Srgrimeserror(num) 2551553Srgrimes int num; 2561553Srgrimes{ 2571553Srgrimes 2581553Srgrimes DEBUG2("rmtd: E %d (%s)\n", num, strerror(num)); 25922464Simp (void)snprintf(resp, sizeof(resp), "E%d\n%s\n", num, strerror(num)); 26080381Ssheldonh (void)write(STDOUT_FILENO, resp, strlen(resp)); 2611553Srgrimes} 262