1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if !defined(lint) && defined(DOSCCS) 8: char copyright[] = 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: 12: static char sccsid[] = "@(#)rmt.c 5.2.1 (2.11BSD) 1996/3/22"; 13: #endif 14: 15: /* 16: * rmt 17: */ 18: #include <stdio.h> 19: #include <sgtty.h> 20: #include <sys/types.h> 21: #include <sys/socket.h> 22: #include <sys/mtio.h> 23: #include <errno.h> 24: #include <stdlib.h> 25: #include <unistd.h> 26: #include <string.h> 27: 28: int tape = -1; 29: 30: char *record; 31: int maxrecsize = -1; 32: char *checkbuf(); 33: 34: #define SSIZE 64 35: char device[SSIZE]; 36: char count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE]; 37: char resp[BUFSIZ]; 38: 39: FILE *debug; 40: #define DEBUG(f) if (debug) fprintf(debug, f) 41: #define DEBUG1(f,a) if (debug) fprintf(debug, f, a) 42: #define DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2) 43: 44: main(argc, argv) 45: int argc; 46: char **argv; 47: { 48: int rval; 49: char c; 50: int n, i, cc; 51: 52: argc--, argv++; 53: if (argc > 0) { 54: debug = fopen(*argv, "w"); 55: if (debug == 0) 56: exit(1); 57: (void) setbuf(debug, (char *)0); 58: } 59: top: 60: errno = 0; 61: rval = 0; 62: if (read(0, &c, 1) != 1) 63: exit(0); 64: switch (c) { 65: 66: case 'O': 67: if (tape >= 0) 68: (void) close(tape); 69: getstring(device); getstring(mode); 70: DEBUG2("rmtd: O %s %s\n", device, mode); 71: tape = open(device, atoi(mode)); 72: if (tape < 0) 73: goto ioerror; 74: goto respond; 75: 76: case 'C': 77: DEBUG("rmtd: C\n"); 78: getstring(device); /* discard */ 79: if (close(tape) < 0) 80: goto ioerror; 81: tape = -1; 82: goto respond; 83: 84: case 'L': 85: getstring(count); getstring(pos); 86: DEBUG2("rmtd: L %s %s\n", count, pos); 87: rval = lseek(tape, atol(count), atoi(pos)); 88: if (rval < 0) 89: goto ioerror; 90: goto respond; 91: 92: case 'W': 93: getstring(count); 94: n = atoi(count); 95: DEBUG1("rmtd: W %s\n", count); 96: record = checkbuf(record, n); 97: for (i = 0; i < n; i += cc) { 98: cc = read(0, &record[i], n - i); 99: if (cc <= 0) { 100: DEBUG("rmtd: premature eof\n"); 101: exit(2); 102: } 103: } 104: rval = write(tape, record, n); 105: if (rval < 0) 106: goto ioerror; 107: goto respond; 108: 109: case 'R': 110: getstring(count); 111: DEBUG1("rmtd: R %s\n", count); 112: n = atoi(count); 113: record = checkbuf(record, n); 114: rval = read(tape, record, n); 115: if (rval < 0) 116: goto ioerror; 117: (void) sprintf(resp, "A%d\n", rval); 118: (void) write(1, resp, strlen(resp)); 119: (void) write(1, record, rval); 120: goto top; 121: 122: case 'I': 123: getstring(op); getstring(count); 124: DEBUG2("rmtd: I %s %s\n", op, count); 125: { struct mtop mtop; 126: mtop.mt_op = atoi(op); 127: mtop.mt_count = atoi(count); 128: if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0) 129: goto ioerror; 130: rval = mtop.mt_count; 131: } 132: goto respond; 133: 134: case 'S': /* status */ 135: DEBUG("rmtd: S\n"); 136: { struct mtget mtget; 137: if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0) 138: goto ioerror; 139: rval = sizeof (mtget); 140: (void) sprintf(resp, "A%d\n", rval); 141: (void) write(1, resp, strlen(resp)); 142: (void) write(1, (char *)&mtget, sizeof (mtget)); 143: goto top; 144: } 145: 146: default: 147: DEBUG1("rmtd: garbage command %c\n", c); 148: exit(3); 149: } 150: respond: 151: DEBUG1("rmtd: A %d\n", rval); 152: (void) sprintf(resp, "A%d\n", rval); 153: (void) write(1, resp, strlen(resp)); 154: goto top; 155: ioerror: 156: error(errno); 157: goto top; 158: } 159: 160: getstring(bp) 161: char *bp; 162: { 163: register int i; 164: register char *cp = bp; 165: 166: for (i = 0; i < SSIZE; i++) { 167: if (read(0, cp+i, 1) != 1) 168: exit(0); 169: if (cp[i] == '\n') 170: break; 171: } 172: cp[i] = '\0'; 173: } 174: 175: char * 176: checkbuf(record, size) 177: char *record; 178: int size; 179: { 180: 181: if (size <= maxrecsize) 182: return (record); 183: if (record != 0) 184: free(record); 185: record = (char *)malloc(size); 186: if (record == 0) { 187: DEBUG("rmtd: cannot allocate buffer space\n"); 188: exit(4); 189: } 190: maxrecsize = size; 191: while (size > 1024 && 192: setsockopt(0, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0) 193: size -= 1024; 194: return (record); 195: } 196: 197: error(num) 198: int num; 199: { 200: 201: DEBUG2("rmtd: E %d (%s)\n", num, strerror(num)); 202: (void) sprintf(resp, "E%d\n%s\n", num, strerror(num)); 203: (void) write(1, resp, strlen(resp)); 204: }