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 /*LINTLIBRARY*/ 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <sys/types.h> 36 #include <devmgmt.h> 37 #include "libadm.h" 38 #include <stdlib.h> 39 40 #define LABELSIZ 6 41 #define BELL "\007" 42 43 #define FORMFS_MSG ",\\n\\ \\ or [f] to format %s and place a filesystem on it" 44 #define FORMAT_MSG ",\\n\\ \\ or [f] to format the %s" 45 #define MAKEFS_MSG ",\\n\\ \\ or [m] to place a filesystem on %s" 46 #define EJECT_MSG ",\\n\\ \\ or [e] to eject the %s" 47 #define UNLOAD_MSG ",\\n\\ \\ or [u] to unload/offline the %s" 48 #define WLABEL_MSG ",\\n\\ \\ or [w] to write a new label on the %s" 49 #define OLABEL_MSG ",\\n\\ \\ or [o] to use the current label anyway" 50 #define QUIT_MSG ",\\n\\ \\ or [q] to quit" 51 52 #define ERR_ACCESS "\n%s (%s) cannot be accessed.\n" 53 #define ERR_FMT "\nAttempt to format %s failed.\n" 54 #define ERR_MKFS "\nAttempt to place filesystem on %s failed.\n" 55 #define ERR_REMOVE "\nExecution of \"removecmd\"[%s] failed.\n" 56 57 static void elabel(void); 58 static void doformat(char *, char *, char *); 59 static void labelerr(char *, char *); 60 static int ckilabel(char *, int); 61 static int insert(char *, char *, int, char *); 62 63 static char *cdevice; /* character device name */ 64 static char *pname; /* device presentation name */ 65 static char *volume; /* volume name */ 66 static char origfsname[LABELSIZ+1]; 67 static char origvolname[LABELSIZ+1]; 68 69 /* 70 * Return: 71 * 0 - okay, label matches 72 * 1 - device not accessable 73 * 2 - unknown device (devattr failed) 74 * 3 - user selected quit 75 * 4 - label does not match 76 */ 77 78 /* 79 * macros from labelit to behave correctly for tape 80 * is a kludge, should use devmgmt 81 */ 82 #ifdef RT 83 #define IFTAPE(s) ((strncmp(s, "/dev/mt", 7) == 0) || \ 84 (strncmp(s, "mt", 2) == 0)) 85 #define TAPENAMES "'/dev/mt'" 86 #else 87 #define IFTAPE(s) ((strncmp(s, "/dev/rmt", 8) == 0) || \ 88 (strncmp(s, "rmt", 3) == 0) || (strncmp(s, "/dev/rtp", 8) == 0) || \ 89 (strncmp(s, "rtp", 3) == 0)) 90 #define TAPENAMES "'/dev/rmt' or '/dev/rtp'" 91 #endif 92 93 int 94 getvol(char *device, char *label, int options, char *prompt) 95 { 96 return (_getvol(device, label, options, prompt, NULL)); 97 } 98 99 int 100 _getvol(char *device, char *label, int options, char *prompt, char *norewind) 101 { 102 FILE *tmp; 103 char *advice, *pt; 104 int n, override; 105 106 cdevice = devattr(device, "cdevice"); 107 if ((cdevice == NULL) || !cdevice[0]) { 108 cdevice = devattr(device, "pathname"); 109 if ((cdevice == NULL) || !cdevice) 110 return (2); /* bad device */ 111 } 112 113 pname = devattr(device, "desc"); 114 if (pname == NULL) { 115 pname = devattr(device, "alias"); 116 if (!pname) 117 pname = device; 118 } 119 120 volume = devattr(device, "volume"); 121 122 if (label) { 123 (void) strncpy(origfsname, label, LABELSIZ); 124 origfsname[LABELSIZ] = '\0'; 125 if (pt = strchr(origfsname, ',')) { 126 *pt = '\0'; 127 } 128 if (pt = strchr(label, ',')) { 129 (void) strncpy(origvolname, pt+1, LABELSIZ); 130 origvolname[LABELSIZ] = '\0'; 131 } else 132 origvolname[0] = '\0'; 133 } 134 135 override = 0; 136 for (;;) { 137 if (!(options & DM_BATCH) && volume) { 138 n = insert(device, label, options, prompt); 139 if (n < 0) 140 override++; 141 else if (n) 142 return (n); /* input function failed */ 143 } 144 145 if ((tmp = fopen(norewind ? norewind : cdevice, "r")) == NULL) { 146 /* device was not accessible */ 147 if (options & DM_BATCH) 148 return (1); 149 (void) fprintf(stderr, ERR_ACCESS, pname, cdevice); 150 if ((options & DM_BATCH) || (volume == NULL)) 151 return (1); 152 /* display advice on how to ready device */ 153 if (advice = devattr(device, "advice")) 154 (void) puttext(stderr, advice, 0, 0); 155 continue; 156 } 157 (void) fclose(tmp); 158 159 /* check label on device */ 160 if (label) { 161 if (options & DM_ELABEL) 162 elabel(); 163 else { 164 /* check internal label using /etc/labelit */ 165 if (ckilabel(label, override)) { 166 if ((options & DM_BATCH) || 167 volume == NULL) 168 return (4); 169 continue; 170 } 171 } 172 } 173 break; 174 } 175 return (0); 176 } 177 178 static int 179 ckilabel(char *label, int flag) 180 { 181 FILE *pp; 182 char *pt, *look, buffer[512]; 183 char fsname[LABELSIZ+1], volname[LABELSIZ+1]; 184 char *pvolname, *pfsname; 185 int n, c; 186 187 (void) strncpy(fsname, label, LABELSIZ); 188 fsname[LABELSIZ] = '\0'; 189 if (pt = strchr(fsname, ',')) { 190 *pt = '\0'; 191 } 192 if (pt = strchr(label, ',')) { 193 (void) strncpy(volname, pt+1, LABELSIZ); 194 volname[LABELSIZ] = '\0'; 195 } else 196 volname[0] = '\0'; 197 198 (void) snprintf(buffer, sizeof (buffer), "/etc/labelit %s", cdevice); 199 pp = popen(buffer, "r"); 200 pt = buffer; 201 while ((c = getc(pp)) != EOF) 202 *pt++ = (char)c; 203 *pt = '\0'; 204 (void) pclose(pp); 205 206 pt = buffer; 207 pfsname = pvolname = NULL; 208 look = "Current fsname: "; 209 n = (int)strlen(look); 210 while (*pt) { 211 if (strncmp(pt, look, n) == 0) { 212 *pt = '\0'; 213 pt += strlen(look); 214 if (pfsname == NULL) { 215 pfsname = pt; 216 look = ", Current volname: "; 217 n = (int)strlen(look); 218 } else if (pvolname == NULL) { 219 pvolname = pt; 220 look = ", Blocks: "; 221 n = (int)strlen(look); 222 } else 223 break; 224 } else 225 pt++; 226 } 227 228 if (strcmp(fsname, pfsname) || strcmp(volname, pvolname)) { 229 /* mismatched label */ 230 if (flag) { 231 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 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) snprintf(buffer, sizeof (buffer), 264 "/etc/labelit %s \"%s\" \"%s\" -n 1>&2", 265 cdevice, fsname, volname); 266 } else { 267 (void) snprintf(buffer, sizeof (buffer), 268 "/etc/labelit %s \"%s\" \"%s\" 1>&2", 269 cdevice, fsname, volname); 270 } 271 if (system(buffer)) { 272 (void) fprintf(stderr, "\nWrite of label to %s failed.", pname); 273 return (1); 274 } 275 if (label) 276 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 277 (void) sprintf(label, "%s,%s", fsname, volname); 278 return (0); 279 } 280 281 static void 282 elabel(void) 283 { 284 } 285 286 static int 287 insert(char *device, char *label, int options, char *prompt) 288 { 289 int n; 290 char strval[16], prmpt[BUFSIZ]; 291 char *pt, *keyword[10]; 292 char *fmtcmd; 293 char *mkfscmd; 294 char *voltxt; 295 char *removecmd; 296 char *dev_type; 297 298 voltxt = (volume ? volume : "volume"); 299 300 fmtcmd = devattr(device, "fmtcmd"); 301 mkfscmd = devattr(device, "mkfscmd"); 302 removecmd = devattr(device, "removecmd"); 303 dev_type = devattr(device, "type"); 304 305 if (prompt) { 306 (void) strlcpy(prmpt, prompt, sizeof (prmpt)); 307 for (pt = prmpt; *prompt; ) { 308 if ((*prompt == '\\') && (prompt[1] == '%')) 309 prompt++; 310 else if (*prompt == '%') { 311 switch (prompt[1]) { 312 case 'v': 313 (void) strcpy(pt, voltxt); 314 break; 315 316 case 'p': 317 (void) strcpy(pt, pname); 318 break; 319 320 default: 321 *pt = '\0'; 322 break; 323 } 324 pt = pt + strlen(pt); 325 prompt += 2; 326 continue; 327 } 328 *pt++ = *prompt++; 329 } 330 *pt = '\0'; 331 } else { 332 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 333 (void) sprintf(prmpt, "Insert a %s into %s.", voltxt, pname); 334 if (label && (options & DM_ELABEL)) { 335 (void) strcat(prmpt, " The following external label "); 336 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 337 (void) sprintf(prmpt+strlen(prmpt), 338 " should appear on the %s:\\n\\t%s", 339 voltxt, label); 340 } 341 if (label && !(options & DM_ELABEL)) { 342 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 343 (void) sprintf(prmpt+strlen(prmpt), 344 " The %s should be internally labeled as follows:", 345 voltxt); 346 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 347 (void) sprintf(prmpt+strlen(prmpt), 348 "\\n\\t%s\\n", label); 349 } 350 } 351 352 pt = prompt = prmpt + strlen(prmpt); 353 354 n = 0; 355 pt += sprintf(pt, "\\nType [go] when ready"); 356 keyword[n++] = "go"; 357 358 if (options & DM_FORMFS) { 359 if (fmtcmd && *fmtcmd && mkfscmd && *mkfscmd) { 360 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 361 pt += sprintf(pt, FORMFS_MSG, voltxt); 362 keyword[n++] = "f"; 363 } else if (fmtcmd && *fmtcmd) { 364 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 365 pt += sprintf(pt, FORMAT_MSG, voltxt); 366 keyword[n++] = "f"; 367 } 368 if (mkfscmd && *mkfscmd) { 369 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 370 pt += sprintf(pt, MAKEFS_MSG, voltxt); 371 keyword[n++] = "m"; 372 } 373 } else if (options & DM_FORMAT) { 374 if (fmtcmd && *fmtcmd) { 375 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 376 pt += sprintf(pt, FORMAT_MSG, voltxt); 377 keyword[n++] = "f"; 378 } 379 } 380 if (options & DM_WLABEL) { 381 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 382 pt += sprintf(pt, WLABEL_MSG, voltxt); 383 keyword[n++] = "w"; 384 } 385 if (options & DM_OLABEL) { 386 pt += sprintf(pt, OLABEL_MSG); 387 keyword[n++] = "o"; 388 } 389 if (removecmd && *removecmd && dev_type && *dev_type) { 390 if (strcmp(dev_type, "diskette") == 0) { 391 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 392 pt += sprintf(pt, EJECT_MSG, voltxt); 393 keyword[n++] = "e"; 394 } else { 395 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 396 pt += sprintf(pt, UNLOAD_MSG, voltxt); 397 keyword[n++] = "u"; 398 } 399 } 400 keyword[n] = NULL; 401 if (ckquit) 402 pt += sprintf(pt, QUIT_MSG); 403 *pt++ = ':'; 404 *pt = '\0'; 405 406 pt = prmpt; 407 (void) fprintf(stderr, BELL); 408 for (;;) { 409 if (n = ckkeywd(strval, keyword, NULL, NULL, NULL, pt)) 410 return (n); 411 412 pt = prompt; /* next prompt is only partial */ 413 if (*strval == 'f') { 414 if (options & DM_FORMFS) 415 doformat(voltxt, fmtcmd, mkfscmd); 416 else 417 doformat(voltxt, fmtcmd, NULL); 418 continue; 419 } else if (*strval == 'm') { 420 doformat(voltxt, NULL, mkfscmd); 421 continue; 422 } else if (*strval == 'e' || *strval == 'u') { 423 (void) doremovecmd(device, 1); 424 continue; 425 } else if (*strval == 'w') { 426 (void) wilabel(label); 427 continue; 428 } else if (*strval == 'o') 429 return (-1); 430 break; 431 } 432 return (0); 433 } 434 435 static void 436 doformat(char *voltxt, char *fmtcmd, char *mkfscmd) 437 { 438 char buffer[512]; 439 440 if (fmtcmd && *fmtcmd) { 441 (void) fprintf(stderr, "\t[%s]\n", fmtcmd); 442 (void) snprintf(buffer, sizeof (buffer), "(%s) 1>&2", fmtcmd); 443 if (system(buffer)) { 444 (void) fprintf(stderr, ERR_FMT, voltxt); 445 return; 446 } 447 } 448 if (mkfscmd && *mkfscmd) { 449 (void) fprintf(stderr, "\t[%s]\n", mkfscmd); 450 (void) snprintf(buffer, sizeof (buffer), "(%s) 1>&2", mkfscmd); 451 if (system(buffer)) { 452 (void) fprintf(stderr, ERR_MKFS, voltxt); 453 return; 454 } 455 } 456 } 457 458 void 459 doremovecmd(char *device, int echo) 460 { 461 char *removecmd; 462 char buffer[512]; 463 464 if (device && *device) { 465 removecmd = devattr(device, "removecmd"); 466 if (removecmd && *removecmd) { 467 if (echo) 468 (void) fprintf(stderr, "\t[%s]\n", removecmd); 469 (void) snprintf(buffer, sizeof (buffer), 470 "(%s) 1>&2", removecmd); 471 if (system(buffer)) { 472 if (echo) 473 (void) fprintf(stderr, ERR_REMOVE, 474 removecmd); 475 return; 476 } 477 } 478 } 479 } 480 481 static void 482 labelerr(char *fsname, char *volname) 483 { 484 (void) fprintf(stderr, "\nLabel incorrect.\n"); 485 if (volume) 486 (void) fprintf(stderr, 487 "The internal label on the inserted %s is\n", volume); 488 else 489 (void) fprintf(stderr, "The internal label for %s is", pname); 490 (void) fprintf(stderr, "\t%s,%s\n", fsname, volname); 491 } 492