1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1997, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 /*LINTLIBRARY*/ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <sys/types.h> 37 #include <devmgmt.h> 38 #include "libadm.h" 39 #include <stdlib.h> 40 41 #define LABELSIZ 6 42 #define BELL "\007" 43 44 #define FORMFS_MSG ",\\n\\ \\ or [f] to format %s and place a filesystem on it" 45 #define FORMAT_MSG ",\\n\\ \\ or [f] to format the %s" 46 #define MAKEFS_MSG ",\\n\\ \\ or [m] to place a filesystem on %s" 47 #define EJECT_MSG ",\\n\\ \\ or [e] to eject the %s" 48 #define UNLOAD_MSG ",\\n\\ \\ or [u] to unload/offline the %s" 49 #define WLABEL_MSG ",\\n\\ \\ or [w] to write a new label on the %s" 50 #define OLABEL_MSG ",\\n\\ \\ or [o] to use the current label anyway" 51 #define QUIT_MSG ",\\n\\ \\ or [q] to quit" 52 53 #define ERR_ACCESS "\n%s (%s) cannot be accessed.\n" 54 #define ERR_FMT "\nAttempt to format %s failed.\n" 55 #define ERR_MKFS "\nAttempt to place filesystem on %s failed.\n" 56 #define ERR_REMOVE "\nExecution of \"removecmd\"[%s] failed.\n" 57 58 static void elabel(void); 59 static void doformat(char *, char *, char *); 60 static void labelerr(char *, char *); 61 static int ckilabel(char *, int); 62 static int insert(char *, char *, int, char *); 63 64 static char *cdevice; /* character device name */ 65 static char *pname; /* device presentation name */ 66 static char *volume; /* volume name */ 67 static char origfsname[LABELSIZ+1]; 68 static char origvolname[LABELSIZ+1]; 69 70 /* 71 * Return: 72 * 0 - okay, label matches 73 * 1 - device not accessable 74 * 2 - unknown device (devattr failed) 75 * 3 - user selected quit 76 * 4 - label does not match 77 */ 78 79 /* 80 * macros from labelit to behave correctly for tape 81 * is a kludge, should use devmgmt 82 */ 83 #ifdef RT 84 #define IFTAPE(s) ((strncmp(s, "/dev/mt", 7) == 0) || \ 85 (strncmp(s, "mt", 2) == 0)) 86 #define TAPENAMES "'/dev/mt'" 87 #else 88 #define IFTAPE(s) ((strncmp(s, "/dev/rmt", 8) == 0) || \ 89 (strncmp(s, "rmt", 3) == 0) || (strncmp(s, "/dev/rtp", 8) == 0) || \ 90 (strncmp(s, "rtp", 3) == 0)) 91 #define TAPENAMES "'/dev/rmt' or '/dev/rtp'" 92 #endif 93 94 int 95 getvol(char *device, char *label, int options, char *prompt) 96 { 97 return (_getvol(device, label, options, prompt, NULL)); 98 } 99 100 int 101 _getvol(char *device, char *label, int options, char *prompt, char *norewind) 102 { 103 FILE *tmp; 104 char *advice, *pt; 105 int n, override; 106 107 cdevice = devattr(device, "cdevice"); 108 if ((cdevice == NULL) || !cdevice[0]) { 109 cdevice = devattr(device, "pathname"); 110 if ((cdevice == NULL) || !cdevice) 111 return (2); /* bad device */ 112 } 113 114 pname = devattr(device, "desc"); 115 if (pname == NULL) { 116 pname = devattr(device, "alias"); 117 if (!pname) 118 pname = device; 119 } 120 121 volume = devattr(device, "volume"); 122 123 if (label) { 124 (void) strncpy(origfsname, label, LABELSIZ); 125 origfsname[LABELSIZ] = '\0'; 126 if (pt = strchr(origfsname, ',')) { 127 *pt = '\0'; 128 } 129 if (pt = strchr(label, ',')) { 130 (void) strncpy(origvolname, pt+1, LABELSIZ); 131 origvolname[LABELSIZ] = '\0'; 132 } else 133 origvolname[0] = '\0'; 134 } 135 136 override = 0; 137 for (;;) { 138 if (!(options & DM_BATCH) && volume) { 139 n = insert(device, label, options, prompt); 140 if (n < 0) 141 override++; 142 else if (n) 143 return (n); /* input function failed */ 144 } 145 146 if ((tmp = fopen(norewind ? norewind : cdevice, "r")) == NULL) { 147 /* device was not accessible */ 148 if (options & DM_BATCH) 149 return (1); 150 (void) fprintf(stderr, ERR_ACCESS, pname, cdevice); 151 if ((options & DM_BATCH) || (volume == NULL)) 152 return (1); 153 /* display advice on how to ready device */ 154 if (advice = devattr(device, "advice")) 155 (void) puttext(stderr, advice, 0, 0); 156 continue; 157 } 158 (void) fclose(tmp); 159 160 /* check label on device */ 161 if (label) { 162 if (options & DM_ELABEL) 163 elabel(); 164 else { 165 /* check internal label using /etc/labelit */ 166 if (ckilabel(label, override)) { 167 if ((options & DM_BATCH) || 168 volume == NULL) 169 return (4); 170 continue; 171 } 172 } 173 } 174 break; 175 } 176 return (0); 177 } 178 179 static int 180 ckilabel(char *label, int flag) 181 { 182 FILE *pp; 183 char *pt, *look, buffer[512]; 184 char fsname[LABELSIZ+1], volname[LABELSIZ+1]; 185 char *pvolname, *pfsname; 186 int n, c; 187 188 (void) strncpy(fsname, label, LABELSIZ); 189 fsname[LABELSIZ] = '\0'; 190 if (pt = strchr(fsname, ',')) { 191 *pt = '\0'; 192 } 193 if (pt = strchr(label, ',')) { 194 (void) strncpy(volname, pt+1, LABELSIZ); 195 volname[LABELSIZ] = '\0'; 196 } else 197 volname[0] = '\0'; 198 199 (void) sprintf(buffer, "/etc/labelit %s", cdevice); 200 pp = popen(buffer, "r"); 201 pt = buffer; 202 while ((c = getc(pp)) != EOF) 203 *pt++ = (char)c; 204 *pt = '\0'; 205 (void) pclose(pp); 206 207 pt = buffer; 208 pfsname = pvolname = NULL; 209 look = "Current fsname: "; 210 n = (int)strlen(look); 211 while (*pt) { 212 if (strncmp(pt, look, n) == 0) { 213 *pt = '\0'; 214 pt += strlen(look); 215 if (pfsname == NULL) { 216 pfsname = pt; 217 look = ", Current volname: "; 218 n = (int)strlen(look); 219 } else if (pvolname == NULL) { 220 pvolname = pt; 221 look = ", Blocks: "; 222 n = (int)strlen(look); 223 } else 224 break; 225 } else 226 pt++; 227 } 228 229 if (strcmp(fsname, pfsname) || strcmp(volname, pvolname)) { 230 /* mismatched label */ 231 if (flag) { 232 (void) sprintf(label, "%s,%s", pfsname, pvolname); 233 } else { 234 labelerr(pfsname, pvolname); 235 return (1); 236 } 237 } 238 return (0); 239 } 240 241 static int 242 wilabel(char *label) 243 { 244 char buffer[512]; 245 char fsname[LABELSIZ+1]; 246 char volname[LABELSIZ+1]; 247 int n; 248 249 if (!label || !strlen(origfsname)) { 250 if (n = ckstr(fsname, NULL, LABELSIZ, NULL, NULL, NULL, 251 "Enter text for fsname label:")) 252 return (n); 253 } else 254 (void) strcpy(fsname, origfsname); 255 if (!label || !strlen(origvolname)) { 256 if (n = ckstr(volname, NULL, LABELSIZ, NULL, NULL, NULL, 257 "Enter text for volume label:")) 258 return (n); 259 } else 260 (void) strcpy(volname, origvolname); 261 262 if (IFTAPE(cdevice)) { 263 (void) sprintf(buffer, "/etc/labelit %s \"%s\" \"%s\" -n 1>&2", 264 cdevice, fsname, volname); 265 } else { 266 (void) sprintf(buffer, "/etc/labelit %s \"%s\" \"%s\" 1>&2", 267 cdevice, fsname, volname); 268 } 269 if (system(buffer)) { 270 (void) fprintf(stderr, "\nWrite of label to %s failed.", pname); 271 return (1); 272 } 273 if (label) 274 (void) sprintf(label, "%s,%s", fsname, volname); 275 return (0); 276 } 277 278 static void 279 elabel(void) 280 { 281 } 282 283 static int 284 insert(char *device, char *label, int options, char *prompt) 285 { 286 int n; 287 char strval[16], prmpt[BUFSIZ]; 288 char *pt, *keyword[10]; 289 char *fmtcmd; 290 char *mkfscmd; 291 char *voltxt; 292 char *removecmd; 293 char *dev_type; 294 295 voltxt = (volume ? volume : "volume"); 296 297 fmtcmd = devattr(device, "fmtcmd"); 298 mkfscmd = devattr(device, "mkfscmd"); 299 removecmd = devattr(device, "removecmd"); 300 dev_type = devattr(device, "type"); 301 302 if (prompt) { 303 (void) strcpy(prmpt, prompt); 304 for (pt = prmpt; *prompt; ) { 305 if ((*prompt == '\\') && (prompt[1] == '%')) 306 prompt++; 307 else if (*prompt == '%') { 308 switch (prompt[1]) { 309 case 'v': 310 (void) strcpy(pt, voltxt); 311 break; 312 313 case 'p': 314 (void) strcpy(pt, pname); 315 break; 316 317 default: 318 *pt = '\0'; 319 break; 320 } 321 pt = pt + strlen(pt); 322 prompt += 2; 323 continue; 324 } 325 *pt++ = *prompt++; 326 } 327 *pt = '\0'; 328 } else { 329 (void) sprintf(prmpt, "Insert a %s into %s.", voltxt, pname); 330 if (label && (options & DM_ELABEL)) { 331 (void) strcat(prmpt, " The following external label "); 332 (void) sprintf(prmpt+strlen(prmpt), 333 " should appear on the %s:\\n\\t%s", 334 voltxt, label); 335 } 336 if (label && !(options & DM_ELABEL)) { 337 (void) sprintf(prmpt+strlen(prmpt), 338 " The %s should be internally labeled as follows:", 339 voltxt); 340 (void) sprintf(prmpt+strlen(prmpt), 341 "\\n\\t%s\\n", label); 342 } 343 } 344 345 pt = prompt = prmpt + strlen(prmpt); 346 347 n = 0; 348 pt += sprintf(pt, "\\nType [go] when ready"); 349 keyword[n++] = "go"; 350 351 if (options & DM_FORMFS) { 352 if (fmtcmd && *fmtcmd && mkfscmd && *mkfscmd) { 353 pt += sprintf(pt, FORMFS_MSG, voltxt); 354 keyword[n++] = "f"; 355 } else if (fmtcmd && *fmtcmd) { 356 pt += sprintf(pt, FORMAT_MSG, voltxt); 357 keyword[n++] = "f"; 358 } 359 if (mkfscmd && *mkfscmd) { 360 pt += sprintf(pt, MAKEFS_MSG, voltxt); 361 keyword[n++] = "m"; 362 } 363 } else if (options & DM_FORMAT) { 364 if (fmtcmd && *fmtcmd) { 365 pt += sprintf(pt, FORMAT_MSG, voltxt); 366 keyword[n++] = "f"; 367 } 368 } 369 if (options & DM_WLABEL) { 370 pt += sprintf(pt, WLABEL_MSG, voltxt); 371 keyword[n++] = "w"; 372 } 373 if (options & DM_OLABEL) { 374 pt += sprintf(pt, OLABEL_MSG); 375 keyword[n++] = "o"; 376 } 377 if (removecmd && *removecmd && dev_type && *dev_type) { 378 if (strcmp(dev_type, "diskette") == 0) { 379 pt += sprintf(pt, EJECT_MSG, voltxt); 380 keyword[n++] = "e"; 381 } else { 382 pt += sprintf(pt, UNLOAD_MSG, voltxt); 383 keyword[n++] = "u"; 384 } 385 } 386 keyword[n] = NULL; 387 if (ckquit) 388 pt += sprintf(pt, QUIT_MSG); 389 *pt++ = ':'; 390 *pt = '\0'; 391 392 pt = prmpt; 393 (void) fprintf(stderr, BELL); 394 for (;;) { 395 if (n = ckkeywd(strval, keyword, NULL, NULL, NULL, pt)) 396 return (n); 397 398 pt = prompt; /* next prompt is only partial */ 399 if (*strval == 'f') { 400 if (options & DM_FORMFS) 401 doformat(voltxt, fmtcmd, mkfscmd); 402 else 403 doformat(voltxt, fmtcmd, NULL); 404 continue; 405 } else if (*strval == 'm') { 406 doformat(voltxt, NULL, mkfscmd); 407 continue; 408 } else if (*strval == 'e' || *strval == 'u') { 409 (void) doremovecmd(device, 1); 410 continue; 411 } else if (*strval == 'w') { 412 (void) wilabel(label); 413 continue; 414 } else if (*strval == 'o') 415 return (-1); 416 break; 417 } 418 return (0); 419 } 420 421 static void 422 doformat(char *voltxt, char *fmtcmd, char *mkfscmd) 423 { 424 char buffer[512]; 425 426 if (fmtcmd && *fmtcmd) { 427 (void) fprintf(stderr, "\t[%s]\n", fmtcmd); 428 (void) sprintf(buffer, "(%s) 1>&2", fmtcmd); 429 if (system(buffer)) { 430 (void) fprintf(stderr, ERR_FMT, voltxt); 431 return; 432 } 433 } 434 if (mkfscmd && *mkfscmd) { 435 (void) fprintf(stderr, "\t[%s]\n", mkfscmd); 436 (void) sprintf(buffer, "(%s) 1>&2", mkfscmd); 437 if (system(buffer)) { 438 (void) fprintf(stderr, ERR_MKFS, voltxt); 439 return; 440 } 441 } 442 } 443 444 void 445 doremovecmd(char *device, int echo) 446 { 447 char *removecmd; 448 char buffer[512]; 449 450 if (device && *device) { 451 removecmd = devattr(device, "removecmd"); 452 if (removecmd && *removecmd) { 453 if (echo) 454 (void) fprintf(stderr, "\t[%s]\n", removecmd); 455 (void) sprintf(buffer, "(%s) 1>&2", removecmd); 456 if (system(buffer)) { 457 if (echo) 458 (void) fprintf(stderr, ERR_REMOVE, 459 removecmd); 460 return; 461 } 462 } 463 } 464 } 465 466 static void 467 labelerr(char *fsname, char *volname) 468 { 469 (void) fprintf(stderr, "\nLabel incorrect.\n"); 470 if (volume) 471 (void) fprintf(stderr, 472 "The internal label on the inserted %s is\n", volume); 473 else 474 (void) fprintf(stderr, "The internal label for %s is", pname); 475 (void) fprintf(stderr, "\t%s,%s\n", fsname, volname); 476 } 477