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