1 /*
2 * Copyright (c) 1980, 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) 1980, 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[] = "@(#)mt.c 8.2 (Berkeley) 05/04/95";
16 #endif /* not lint */
17
18 /*
19 * mt --
20 * magnetic tape manipulation program
21 */
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <sys/mtio.h>
25
26 #include <ctype.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 struct commands {
35 char *c_name;
36 int c_code;
37 int c_ronly;
38 } com[] = {
39 { "bsf", MTBSF, 1 },
40 { "bsr", MTBSR, 1 },
41 { "eof", MTWEOF, 0 },
42 { "fsf", MTFSF, 1 },
43 { "fsr", MTFSR, 1 },
44 { "offline", MTOFFL, 1 },
45 { "rewind", MTREW, 1 },
46 { "rewoffl", MTOFFL, 1 },
47 { "status", MTNOP, 1 },
48 { "weof", MTWEOF, 0 },
49 { NULL }
50 };
51
52 void err __P((const char *, ...));
53 void printreg __P((char *, u_int, char *));
54 void status __P((struct mtget *));
55 void usage __P((void));
56
57 int
main(argc,argv)58 main(argc, argv)
59 int argc;
60 char *argv[];
61 {
62 register struct commands *comp;
63 struct mtget mt_status;
64 struct mtop mt_com;
65 int ch, len, mtfd;
66 char *p, *tape;
67
68 if ((tape = getenv("TAPE")) == NULL)
69 tape = DEFTAPE;
70
71 while ((ch = getopt(argc, argv, "f:t:")) != EOF)
72 switch(ch) {
73 case 'f':
74 case 't':
75 tape = optarg;
76 break;
77 case '?':
78 default:
79 usage();
80 }
81 argc -= optind;
82 argv += optind;
83
84 if (argc < 1 || argc > 2)
85 usage();
86
87 len = strlen(p = *argv++);
88 for (comp = com;; comp++) {
89 if (comp->c_name == NULL)
90 err("%s: unknown command", p);
91 if (strncmp(p, comp->c_name, len) == 0)
92 break;
93 }
94 if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0)
95 err("%s: %s", tape, strerror(errno));
96 if (comp->c_code != MTNOP) {
97 mt_com.mt_op = comp->c_code;
98 if (*argv) {
99 mt_com.mt_count = strtol(*argv, &p, 10);
100 if (mt_com.mt_count <= 0 || *p)
101 err("%s: illegal count", *argv);
102 }
103 else
104 mt_com.mt_count = 1;
105 if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0)
106 err("%s: %s: %s", tape, comp->c_name, strerror(errno));
107 } else {
108 if (ioctl(mtfd, MTIOCGET, &mt_status) < 0)
109 err("%s", strerror(errno));
110 status(&mt_status);
111 }
112 exit (0);
113 /* NOTREACHED */
114 }
115
116 #ifdef vax
117 #include <vax/mba/mtreg.h>
118 #include <vax/mba/htreg.h>
119
120 #include <vax/uba/utreg.h>
121 #include <vax/uba/tmreg.h>
122 #undef b_repcnt /* argh */
123 #include <vax/uba/tsreg.h>
124 #endif
125
126 #ifdef sun
127 #include <sundev/tmreg.h>
128 #include <sundev/arreg.h>
129 #endif
130
131 #ifdef tahoe
132 #include <tahoe/vba/cyreg.h>
133 #endif
134
135 struct tape_desc {
136 short t_type; /* type of magtape device */
137 char *t_name; /* printing name */
138 char *t_dsbits; /* "drive status" register */
139 char *t_erbits; /* "error" register */
140 } tapes[] = {
141 #ifdef vax
142 { MT_ISTS, "ts11", 0, TSXS0_BITS },
143 { MT_ISHT, "tm03", HTDS_BITS, HTER_BITS },
144 { MT_ISTM, "tm11", 0, TMER_BITS },
145 { MT_ISMT, "tu78", MTDS_BITS, 0 },
146 { MT_ISUT, "tu45", UTDS_BITS, UTER_BITS },
147 #endif
148 #ifdef sun
149 { MT_ISCPC, "TapeMaster", TMS_BITS, 0 },
150 { MT_ISAR, "Archive", ARCH_CTRL_BITS, ARCH_BITS },
151 #endif
152 #ifdef tahoe
153 { MT_ISCY, "cipher", CYS_BITS, CYCW_BITS },
154 #endif
155 { 0 }
156 };
157
158 /*
159 * Interpret the status buffer returned
160 */
161 void
status(bp)162 status(bp)
163 register struct mtget *bp;
164 {
165 register struct tape_desc *mt;
166
167 for (mt = tapes;; mt++) {
168 if (mt->t_type == 0) {
169 (void)printf("%d: unknown tape drive type\n",
170 bp->mt_type);
171 return;
172 }
173 if (mt->t_type == bp->mt_type)
174 break;
175 }
176 (void)printf("%s tape drive, residual=%d\n", mt->t_name, bp->mt_resid);
177 printreg("ds", bp->mt_dsreg, mt->t_dsbits);
178 printreg("\ner", bp->mt_erreg, mt->t_erbits);
179 (void)putchar('\n');
180 }
181
182 /*
183 * Print a register a la the %b format of the kernel's printf.
184 */
185 void
printreg(s,v,bits)186 printreg(s, v, bits)
187 char *s;
188 register u_int v;
189 register char *bits;
190 {
191 register int i, any = 0;
192 register char c;
193
194 if (bits && *bits == 8)
195 printf("%s=%o", s, v);
196 else
197 printf("%s=%x", s, v);
198 bits++;
199 if (v && bits) {
200 putchar('<');
201 while (i = *bits++) {
202 if (v & (1 << (i-1))) {
203 if (any)
204 putchar(',');
205 any = 1;
206 for (; (c = *bits) > 32; bits++)
207 putchar(c);
208 } else
209 for (; *bits > 32; bits++)
210 ;
211 }
212 putchar('>');
213 }
214 }
215
216 void
usage()217 usage()
218 {
219 (void)fprintf(stderr, "usage: mt [-f device] command [ count ]\n");
220 exit(1);
221 }
222
223 #if __STDC__
224 #include <stdarg.h>
225 #else
226 #include <varargs.h>
227 #endif
228
229 void
230 #if __STDC__
err(const char * fmt,...)231 err(const char *fmt, ...)
232 #else
233 err(fmt, va_alist)
234 char *fmt;
235 va_dcl
236 #endif
237 {
238 va_list ap;
239 #if __STDC__
240 va_start(ap, fmt);
241 #else
242 va_start(ap);
243 #endif
244 (void)fprintf(stderr, "mt: ");
245 (void)vfprintf(stderr, fmt, ap);
246 va_end(ap);
247 (void)fprintf(stderr, "\n");
248 exit(1);
249 /* NOTREACHED */
250 }
251