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 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 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 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 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__ 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