xref: /original-bsd/usr.sbin/rmt/rmt.c (revision 0722fc5c)
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.1 (Berkeley) 05/28/85";
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 char	*sprintf();
42 long	lseek();
43 
44 FILE	*debug;
45 #define	DEBUG(f)	if (debug) fprintf(debug, f)
46 #define	DEBUG1(f,a)	if (debug) fprintf(debug, f, a)
47 #define	DEBUG2(f,a1,a2)	if (debug) fprintf(debug, f, a1, a2)
48 
49 main(argc, argv)
50 	int argc;
51 	char **argv;
52 {
53 	int rval;
54 	char c;
55 	int n, i, cc;
56 
57 	argc--, argv++;
58 	if (argc > 0) {
59 		debug = fopen(*argv, "w");
60 		if (debug == 0)
61 			exit(1);
62 		(void) setbuf(debug, (char *)0);
63 	}
64 top:
65 	errno = 0;
66 	rval = 0;
67 	if (read(0, &c, 1) != 1)
68 		exit(0);
69 	switch (c) {
70 
71 	case 'O':
72 		if (tape >= 0)
73 			(void) close(tape);
74 		getstring(device); getstring(mode);
75 		DEBUG2("rmtd: O %s %s\n", device, mode);
76 		tape = open(device, atoi(mode));
77 		if (tape < 0)
78 			goto ioerror;
79 		goto respond;
80 
81 	case 'C':
82 		DEBUG("rmtd: C\n");
83 		getstring(device);		/* discard */
84 		if (close(tape) < 0)
85 			goto ioerror;
86 		tape = -1;
87 		goto respond;
88 
89 	case 'L':
90 		getstring(count); getstring(pos);
91 		DEBUG2("rmtd: L %s %s\n", count, pos);
92 		rval = lseek(tape, (long) atoi(count), atoi(pos));
93 		if (rval < 0)
94 			goto ioerror;
95 		goto respond;
96 
97 	case 'W':
98 		getstring(count);
99 		n = atoi(count);
100 		DEBUG1("rmtd: W %s\n", count);
101 		record = checkbuf(record, n);
102 		for (i = 0; i < n; i += cc) {
103 			cc = read(0, &record[i], n - i);
104 			if (cc <= 0) {
105 				DEBUG("rmtd: premature eof\n");
106 				exit(2);
107 			}
108 		}
109 		rval = write(tape, record, n);
110 		if (rval < 0)
111 			goto ioerror;
112 		goto respond;
113 
114 	case 'R':
115 		getstring(count);
116 		DEBUG1("rmtd: R %s\n", count);
117 		n = atoi(count);
118 		record = checkbuf(record, n);
119 		rval = read(tape, record, n);
120 		if (rval < 0)
121 			goto ioerror;
122 		(void) sprintf(resp, "A%d\n", rval);
123 		(void) write(1, resp, strlen(resp));
124 		(void) write(1, record, rval);
125 		goto top;
126 
127 	case 'I':
128 		getstring(op); getstring(count);
129 		DEBUG2("rmtd: I %s %s\n", op, count);
130 		{ struct mtop mtop;
131 		  mtop.mt_op = atoi(op);
132 		  mtop.mt_count = atoi(count);
133 		  if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0)
134 			goto ioerror;
135 		  rval = mtop.mt_count;
136 		}
137 		goto respond;
138 
139 	case 'S':		/* status */
140 		DEBUG("rmtd: S\n");
141 		{ struct mtget mtget;
142 		  if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0)
143 			goto ioerror;
144 		  rval = sizeof (mtget);
145 		  (void) sprintf(resp, "A%d\n", rval);
146 		  (void) write(1, resp, strlen(resp));
147 		  (void) write(1, (char *)&mtget, sizeof (mtget));
148 		  goto top;
149 		}
150 
151 	default:
152 		DEBUG1("rmtd: garbage command %c\n", c);
153 		exit(3);
154 	}
155 respond:
156 	DEBUG1("rmtd: A %d\n", rval);
157 	(void) sprintf(resp, "A%d\n", rval);
158 	(void) write(1, resp, strlen(resp));
159 	goto top;
160 ioerror:
161 	error(errno);
162 	goto top;
163 }
164 
165 getstring(bp)
166 	char *bp;
167 {
168 	int i;
169 	char *cp = bp;
170 
171 	for (i = 0; i < SSIZE; i++) {
172 		if (read(0, cp+i, 1) != 1)
173 			exit(0);
174 		if (cp[i] == '\n')
175 			break;
176 	}
177 	cp[i] = '\0';
178 }
179 
180 char *
181 checkbuf(record, size)
182 	char *record;
183 	int size;
184 {
185 	extern char *malloc();
186 
187 	if (size <= maxrecsize)
188 		return (record);
189 	if (record != 0)
190 		free(record);
191 	record = malloc(size);
192 	if (record == 0) {
193 		DEBUG("rmtd: cannot allocate buffer space\n");
194 		exit(4);
195 	}
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