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
getvol(char * device,char * label,int options,char * prompt)95 getvol(char *device, char *label, int options, char *prompt)
96 {
97 return (_getvol(device, label, options, prompt, NULL));
98 }
99
100 int
_getvol(char * device,char * label,int options,char * prompt,char * norewind)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
ckilabel(char * label,int flag)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
wilabel(char * label)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
elabel(void)279 elabel(void)
280 {
281 }
282
283 static int
insert(char * device,char * label,int options,char * prompt)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
doformat(char * voltxt,char * fmtcmd,char * mkfscmd)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
doremovecmd(char * device,int echo)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
labelerr(char * fsname,char * volname)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