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