/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright (c) 1997, by Sun Microsystems, Inc. * All rights reserved. */ /*LINTLIBRARY*/ #include #include #include #include #include "libadm.h" #include #define LABELSIZ 6 #define BELL "\007" #define FORMFS_MSG ",\\n\\ \\ or [f] to format %s and place a filesystem on it" #define FORMAT_MSG ",\\n\\ \\ or [f] to format the %s" #define MAKEFS_MSG ",\\n\\ \\ or [m] to place a filesystem on %s" #define EJECT_MSG ",\\n\\ \\ or [e] to eject the %s" #define UNLOAD_MSG ",\\n\\ \\ or [u] to unload/offline the %s" #define WLABEL_MSG ",\\n\\ \\ or [w] to write a new label on the %s" #define OLABEL_MSG ",\\n\\ \\ or [o] to use the current label anyway" #define QUIT_MSG ",\\n\\ \\ or [q] to quit" #define ERR_ACCESS "\n%s (%s) cannot be accessed.\n" #define ERR_FMT "\nAttempt to format %s failed.\n" #define ERR_MKFS "\nAttempt to place filesystem on %s failed.\n" #define ERR_REMOVE "\nExecution of \"removecmd\"[%s] failed.\n" static void elabel(void); static void doformat(char *, char *, char *); static void labelerr(char *, char *); static int ckilabel(char *, int); static int insert(char *, char *, int, char *); static char *cdevice; /* character device name */ static char *pname; /* device presentation name */ static char *volume; /* volume name */ static char origfsname[LABELSIZ+1]; static char origvolname[LABELSIZ+1]; /* * Return: * 0 - okay, label matches * 1 - device not accessable * 2 - unknown device (devattr failed) * 3 - user selected quit * 4 - label does not match */ /* * macros from labelit to behave correctly for tape * is a kludge, should use devmgmt */ #ifdef RT #define IFTAPE(s) ((strncmp(s, "/dev/mt", 7) == 0) || \ (strncmp(s, "mt", 2) == 0)) #define TAPENAMES "'/dev/mt'" #else #define IFTAPE(s) ((strncmp(s, "/dev/rmt", 8) == 0) || \ (strncmp(s, "rmt", 3) == 0) || (strncmp(s, "/dev/rtp", 8) == 0) || \ (strncmp(s, "rtp", 3) == 0)) #define TAPENAMES "'/dev/rmt' or '/dev/rtp'" #endif int getvol(char *device, char *label, int options, char *prompt) { return (_getvol(device, label, options, prompt, NULL)); } int _getvol(char *device, char *label, int options, char *prompt, char *norewind) { FILE *tmp; char *advice, *pt; int n, override; cdevice = devattr(device, "cdevice"); if ((cdevice == NULL) || !cdevice[0]) { cdevice = devattr(device, "pathname"); if ((cdevice == NULL) || !cdevice) return (2); /* bad device */ } pname = devattr(device, "desc"); if (pname == NULL) { pname = devattr(device, "alias"); if (!pname) pname = device; } volume = devattr(device, "volume"); if (label) { (void) strncpy(origfsname, label, LABELSIZ); origfsname[LABELSIZ] = '\0'; if (pt = strchr(origfsname, ',')) { *pt = '\0'; } if (pt = strchr(label, ',')) { (void) strncpy(origvolname, pt+1, LABELSIZ); origvolname[LABELSIZ] = '\0'; } else origvolname[0] = '\0'; } override = 0; for (;;) { if (!(options & DM_BATCH) && volume) { n = insert(device, label, options, prompt); if (n < 0) override++; else if (n) return (n); /* input function failed */ } if ((tmp = fopen(norewind ? norewind : cdevice, "r")) == NULL) { /* device was not accessible */ if (options & DM_BATCH) return (1); (void) fprintf(stderr, ERR_ACCESS, pname, cdevice); if ((options & DM_BATCH) || (volume == NULL)) return (1); /* display advice on how to ready device */ if (advice = devattr(device, "advice")) (void) puttext(stderr, advice, 0, 0); continue; } (void) fclose(tmp); /* check label on device */ if (label) { if (options & DM_ELABEL) elabel(); else { /* check internal label using /etc/labelit */ if (ckilabel(label, override)) { if ((options & DM_BATCH) || volume == NULL) return (4); continue; } } } break; } return (0); } static int ckilabel(char *label, int flag) { FILE *pp; char *pt, *look, buffer[512]; char fsname[LABELSIZ+1], volname[LABELSIZ+1]; char *pvolname, *pfsname; int n, c; (void) strncpy(fsname, label, LABELSIZ); fsname[LABELSIZ] = '\0'; if (pt = strchr(fsname, ',')) { *pt = '\0'; } if (pt = strchr(label, ',')) { (void) strncpy(volname, pt+1, LABELSIZ); volname[LABELSIZ] = '\0'; } else volname[0] = '\0'; (void) snprintf(buffer, sizeof (buffer), "/etc/labelit %s", cdevice); pp = popen(buffer, "r"); pt = buffer; while ((c = getc(pp)) != EOF) *pt++ = (char)c; *pt = '\0'; (void) pclose(pp); pt = buffer; pfsname = pvolname = NULL; look = "Current fsname: "; n = (int)strlen(look); while (*pt) { if (strncmp(pt, look, n) == 0) { *pt = '\0'; pt += strlen(look); if (pfsname == NULL) { pfsname = pt; look = ", Current volname: "; n = (int)strlen(look); } else if (pvolname == NULL) { pvolname = pt; look = ", Blocks: "; n = (int)strlen(look); } else break; } else pt++; } if (strcmp(fsname, pfsname) || strcmp(volname, pvolname)) { /* mismatched label */ if (flag) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ (void) sprintf(label, "%s,%s", pfsname, pvolname); } else { labelerr(pfsname, pvolname); return (1); } } return (0); } static int wilabel(char *label) { char buffer[512]; char fsname[LABELSIZ+1]; char volname[LABELSIZ+1]; int n; if (!label || !strlen(origfsname)) { if (n = ckstr(fsname, NULL, LABELSIZ, NULL, NULL, NULL, "Enter text for fsname label:")) return (n); } else (void) strcpy(fsname, origfsname); if (!label || !strlen(origvolname)) { if (n = ckstr(volname, NULL, LABELSIZ, NULL, NULL, NULL, "Enter text for volume label:")) return (n); } else (void) strcpy(volname, origvolname); if (IFTAPE(cdevice)) { (void) snprintf(buffer, sizeof (buffer), "/etc/labelit %s \"%s\" \"%s\" -n 1>&2", cdevice, fsname, volname); } else { (void) snprintf(buffer, sizeof (buffer), "/etc/labelit %s \"%s\" \"%s\" 1>&2", cdevice, fsname, volname); } if (system(buffer)) { (void) fprintf(stderr, "\nWrite of label to %s failed.", pname); return (1); } if (label) /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ (void) sprintf(label, "%s,%s", fsname, volname); return (0); } static void elabel(void) { } static int insert(char *device, char *label, int options, char *prompt) { int n; char strval[16], prmpt[BUFSIZ]; char *pt, *keyword[10]; char *fmtcmd; char *mkfscmd; char *voltxt; char *removecmd; char *dev_type; voltxt = (volume ? volume : "volume"); fmtcmd = devattr(device, "fmtcmd"); mkfscmd = devattr(device, "mkfscmd"); removecmd = devattr(device, "removecmd"); dev_type = devattr(device, "type"); if (prompt) { (void) strlcpy(prmpt, prompt, sizeof (prmpt)); for (pt = prmpt; *prompt; ) { if ((*prompt == '\\') && (prompt[1] == '%')) prompt++; else if (*prompt == '%') { switch (prompt[1]) { case 'v': (void) strcpy(pt, voltxt); break; case 'p': (void) strcpy(pt, pname); break; default: *pt = '\0'; break; } pt = pt + strlen(pt); prompt += 2; continue; } *pt++ = *prompt++; } *pt = '\0'; } else { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ (void) sprintf(prmpt, "Insert a %s into %s.", voltxt, pname); if (label && (options & DM_ELABEL)) { (void) strcat(prmpt, " The following external label "); /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ (void) sprintf(prmpt+strlen(prmpt), " should appear on the %s:\\n\\t%s", voltxt, label); } if (label && !(options & DM_ELABEL)) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ (void) sprintf(prmpt+strlen(prmpt), " The %s should be internally labeled as follows:", voltxt); /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ (void) sprintf(prmpt+strlen(prmpt), "\\n\\t%s\\n", label); } } pt = prompt = prmpt + strlen(prmpt); n = 0; pt += sprintf(pt, "\\nType [go] when ready"); keyword[n++] = "go"; if (options & DM_FORMFS) { if (fmtcmd && *fmtcmd && mkfscmd && *mkfscmd) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ pt += sprintf(pt, FORMFS_MSG, voltxt); keyword[n++] = "f"; } else if (fmtcmd && *fmtcmd) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ pt += sprintf(pt, FORMAT_MSG, voltxt); keyword[n++] = "f"; } if (mkfscmd && *mkfscmd) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ pt += sprintf(pt, MAKEFS_MSG, voltxt); keyword[n++] = "m"; } } else if (options & DM_FORMAT) { if (fmtcmd && *fmtcmd) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ pt += sprintf(pt, FORMAT_MSG, voltxt); keyword[n++] = "f"; } } if (options & DM_WLABEL) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ pt += sprintf(pt, WLABEL_MSG, voltxt); keyword[n++] = "w"; } if (options & DM_OLABEL) { pt += sprintf(pt, OLABEL_MSG); keyword[n++] = "o"; } if (removecmd && *removecmd && dev_type && *dev_type) { if (strcmp(dev_type, "diskette") == 0) { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ pt += sprintf(pt, EJECT_MSG, voltxt); keyword[n++] = "e"; } else { /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ pt += sprintf(pt, UNLOAD_MSG, voltxt); keyword[n++] = "u"; } } keyword[n] = NULL; if (ckquit) pt += sprintf(pt, QUIT_MSG); *pt++ = ':'; *pt = '\0'; pt = prmpt; (void) fprintf(stderr, BELL); for (;;) { if (n = ckkeywd(strval, keyword, NULL, NULL, NULL, pt)) return (n); pt = prompt; /* next prompt is only partial */ if (*strval == 'f') { if (options & DM_FORMFS) doformat(voltxt, fmtcmd, mkfscmd); else doformat(voltxt, fmtcmd, NULL); continue; } else if (*strval == 'm') { doformat(voltxt, NULL, mkfscmd); continue; } else if (*strval == 'e' || *strval == 'u') { (void) doremovecmd(device, 1); continue; } else if (*strval == 'w') { (void) wilabel(label); continue; } else if (*strval == 'o') return (-1); break; } return (0); } static void doformat(char *voltxt, char *fmtcmd, char *mkfscmd) { char buffer[512]; if (fmtcmd && *fmtcmd) { (void) fprintf(stderr, "\t[%s]\n", fmtcmd); (void) snprintf(buffer, sizeof (buffer), "(%s) 1>&2", fmtcmd); if (system(buffer)) { (void) fprintf(stderr, ERR_FMT, voltxt); return; } } if (mkfscmd && *mkfscmd) { (void) fprintf(stderr, "\t[%s]\n", mkfscmd); (void) snprintf(buffer, sizeof (buffer), "(%s) 1>&2", mkfscmd); if (system(buffer)) { (void) fprintf(stderr, ERR_MKFS, voltxt); return; } } } void doremovecmd(char *device, int echo) { char *removecmd; char buffer[512]; if (device && *device) { removecmd = devattr(device, "removecmd"); if (removecmd && *removecmd) { if (echo) (void) fprintf(stderr, "\t[%s]\n", removecmd); (void) snprintf(buffer, sizeof (buffer), "(%s) 1>&2", removecmd); if (system(buffer)) { if (echo) (void) fprintf(stderr, ERR_REMOVE, removecmd); return; } } } } static void labelerr(char *fsname, char *volname) { (void) fprintf(stderr, "\nLabel incorrect.\n"); if (volume) (void) fprintf(stderr, "The internal label on the inserted %s is\n", volume); else (void) fprintf(stderr, "The internal label for %s is", pname); (void) fprintf(stderr, "\t%s,%s\n", fsname, volname); }