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