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