diff options
Diffstat (limited to 'usr/src/lib/libadm/common/getvol.c')
-rw-r--r-- | usr/src/lib/libadm/common/getvol.c | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/usr/src/lib/libadm/common/getvol.c b/usr/src/lib/libadm/common/getvol.c new file mode 100644 index 0000000000..f4955073ed --- /dev/null +++ b/usr/src/lib/libadm/common/getvol.c @@ -0,0 +1,476 @@ +/* + * 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" +/*LINTLIBRARY*/ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <devmgmt.h> +#include "libadm.h" +#include <stdlib.h> + +#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) sprintf(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) { + (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) sprintf(buffer, "/etc/labelit %s \"%s\" \"%s\" -n 1>&2", + cdevice, fsname, volname); + } else { + (void) sprintf(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) + (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) strcpy(prmpt, prompt); + 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 { + (void) sprintf(prmpt, "Insert a %s into %s.", voltxt, pname); + if (label && (options & DM_ELABEL)) { + (void) strcat(prmpt, " The following external label "); + (void) sprintf(prmpt+strlen(prmpt), + " should appear on the %s:\\n\\t%s", + voltxt, label); + } + if (label && !(options & DM_ELABEL)) { + (void) sprintf(prmpt+strlen(prmpt), + " The %s should be internally labeled as follows:", + voltxt); + (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) { + pt += sprintf(pt, FORMFS_MSG, voltxt); + keyword[n++] = "f"; + } else if (fmtcmd && *fmtcmd) { + pt += sprintf(pt, FORMAT_MSG, voltxt); + keyword[n++] = "f"; + } + if (mkfscmd && *mkfscmd) { + pt += sprintf(pt, MAKEFS_MSG, voltxt); + keyword[n++] = "m"; + } + } else if (options & DM_FORMAT) { + if (fmtcmd && *fmtcmd) { + pt += sprintf(pt, FORMAT_MSG, voltxt); + keyword[n++] = "f"; + } + } + if (options & DM_WLABEL) { + 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) { + pt += sprintf(pt, EJECT_MSG, voltxt); + keyword[n++] = "e"; + } else { + 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) sprintf(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) sprintf(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) sprintf(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); +} |