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
main(argc,argv)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
getstring(bp)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 *
checkbuf(record,size)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
error(num)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