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