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