xref: /original-bsd/usr.sbin/rmt/rmt.c (revision 09da47ed)
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