xref: /original-bsd/local/ukc/dump/dumplabel.c (revision a9c19d04)
1 #ifndef lint
2 static char *sccsid = "@(#)dumplabel.c	1.3 (UKC) 08/11/87";
3 #endif not lint
4 /***
5 
6 * program name:
7 	dumplabel.c
8 * function:
9 	prints the label from a header
10 	writes a dummy dump header at the start of a tape
11 	Doesn't do any checksum
12 * switches:
13 	-f <tapename>
14 	-r	rewind/offline each tape
15 	-l	label format
16 	followed by list of tape labels in the same format at given to the
17 		locally modified dump program
18 	if no tape labels are given print the details on the start of a tape
19 * libraries used:
20 	standard
21 * compile time parameters:
22 	cc -o dumplabel dumplabel.c
23 * history:
24 	Written August 1987 Peter Collinson UKC
25 
26 ***/
27 #include "dump.h"
28 #include <sys/ioctl.h>
29 #include <sys/mtio.h>
30 
31 #define	LABMAX	100		/* get space for 100 */
32 
33 char	*labarg[LABMAX];	/* vector of map entries */
34 
35 char	*labfmt;		/* format for tape label */
36 
37 int	labct;			/* number of entries */
38 				/* if zero then no labels used */
39 
40 char *tape = "/dev/rmt8";
41 
42 int	dorew;			/* set if rewind offline on exit */
43 int	tapecount;		/* number of tapes dealt with */
44 
45 char	*index();
46 
47 main(argc, argv)
48 char **argv;
49 {	register i;
50 	register char *p;
51 	while (--argc) {
52 		argv++;
53 		if (**argv == '-') {
54 			for (p = *argv; *p; p++)
55 				switch (*p) {
56 
57 				case 'f':
58 					if (--argc > 0) {
59 						argv++;
60 						tape = *argv;
61 					}
62 					break;
63 				case 'r':
64 					dorew++;	/* no rewind/offline */
65 					break;
66 				case 'l':
67 					if (--argc > 0) {
68 						argv++;
69 						labfmt = *argv;
70 					}
71 				}
72 		} else {
73 			storelabelmap(*argv);
74 			if (labfmt && labct)
75 				if (index(labfmt, '%') == NULL)
76 					fprintf(stderr, "Warning - no format specifier (%%s) found in -l argument\n");
77 			for (i = 1; i <= labct; i++)
78 				dolabel(i);
79 			labct = 0;
80 		}
81 	}
82 	if (tapecount == 0) {
83 		if (labfmt) {
84 			labct = 0;
85 			dolabel(1);	/* pretend a volume number of 1 */
86 		} else
87 			printlabel();
88 	}
89 	exit(0);
90 }
91 
92 /*
93  *	Store map list
94  *	The map list
95  *	allows a simple way to specify a range of tapes
96  *	This generates a string which is inserted into the label format
97  *	by use of an sprint operation
98  *
99  *	The basic form here is:
100  *	<string>			a single string
101  *	<string>,<string>,......	a list of strings
102  *	<string>-<string>		a range of strings
103  *					where the string is `incremented'
104  *					to generate a list
105  */
106 storelabelmap(arg)
107 	char *arg;
108 {
109 	register char *ss, *es;
110 	register char *incbase, *incr;
111 	register lastc;
112 	char *labskip();
113 	char *strstore();
114 
115 	/*
116 	 *	Parse the argument looking for a single string
117 	 */
118 	for (ss = arg; *ss; ss = es) {
119 		es = labskip(ss);
120 		lastc = *es;	/* save last character */
121 		*es++ = '\0';	/* make the first label into a string */
122 		if (labct > LABMAX)
123 			labfatal("Too many (> %d) tape labels specified\n", LABMAX);
124 		if (*ss == '\0')
125 			labfatal("Zero length label found\n");
126 		labarg[labct++] = strstore(ss);
127 
128 		if (lastc == 0)
129 			break;		/* end of list */
130 
131 		if (lastc == '-') {
132 			/*
133 			 * this gives a tape range
134 			 * increment the source number until it equals the final
135 			 * value
136 			 */
137 			incbase = ss;
138 			ss = es;
139 			es = labskip(ss);
140 			if (*es == '-')
141 				labfatal("Range has the format <string>-<string>\n");
142 			lastc = *es;
143 			if (lastc)
144 				*es++ = '\0';
145 			/*
146 			 * basic test the source string length must be equal to the
147 			 * end string length
148 			 */
149 			if (strlen(incbase) != strlen(ss))
150 				labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss);
151 			labelrange(incbase, ss);
152 		}
153 	}
154 }
155 
156 /*
157  *	Expand a label range
158  */
159 /* static */
160 labelrange(startrange, endrange)
161 	char *startrange, *endrange;
162 {
163 	register char *incr;
164 	register int carry;
165 
166 
167 	for (incr = startrange + strlen(startrange) - 1;
168 			strcmp(startrange, endrange) != 0; ) {
169 		/* start incrementing */
170 		carry = 0;
171 		do {
172 			if (isdigit(*incr)) {
173 				if (*incr == '9') {
174 					*incr = '0';
175 					carry = 1;
176 				} else
177 					(*incr)++;
178 			} else
179 			if (isupper(*incr)) {
180 				if (*incr == 'Z') {
181 					*incr = 'A';
182 					carry = 1;
183 				} else
184 					(*incr)++;
185 			} else
186 			if (islower(*incr)) {
187 				if (*incr == 'z') {
188 					*incr = 'a';
189 					carry = 1;
190 				} else
191 					(*incr)++;
192 			} else
193 				labfatal("Problem with label map range spec - can only increment alphanumeric values\n");
194 			if (carry) {
195 				incr--;
196 				if (incr < startrange)
197 					labfatal("Problem with label map range spec - end of range reached\n");
198 			}
199 		} while (carry);
200 
201 		if (labct > LABMAX)
202 			labfatal("Too many (> %d) tape labels specified\n", LABMAX);
203 		labarg[labct++] = strstore(startrange);
204 
205 	}
206 }
207 
208 /*
209  *	Store a string using malloc
210  */
211 /* static */
212 char *
213 strstore(arg)
214 	char *arg;
215 {
216 	register len = strlen(arg)+1;
217 	register char *dest;
218 	char *malloc();
219 
220 	dest = malloc(len);
221 	if (dest == NULL)
222 		labfatal("No memory for string storage\n");
223 	bcopy(arg, dest, len);
224 	return(dest);
225 }
226 
227 /*
228  *	Create a tape label from a volume number
229  */
230 char *
231 createlabel(volno)
232 	int volno;
233 {
234 	static char buf[LBLSIZE+LBLSIZE];
235 	char volbuf[8];
236 	register char *arg;
237 
238 
239 	if (labfmt == NULL)
240 		labfmt = "%s";
241 
242 	if (labct == 0)
243 	{	(void) sprintf(volbuf, "%d", volno);
244 		arg = volbuf;
245 	}
246 	else
247 		arg = labarg[volno-1];		/* volumes run 1-> */
248 	(void) sprintf(buf, labfmt, arg);
249 	buf[LBLSIZE-1] = '\0';			/* Truncate to correct size */
250 	return(buf);
251 }
252 
253 /*
254  *	skip forward looking for valid end of label characters
255  */
256 char *
257 labskip(str)
258 register char *str;
259 {	while (*str != ',' && *str != '-' && *str)
260 		str++;
261 	return (str);
262 }
263 
264 /*
265  *	do the actual labelling
266  */
267 dolabel(index)
268 {	register fd;
269 
270 	tapecount++;
271 	askformount(index);
272 
273 	while ((fd = open(tape, 2)) < 0)
274 	{	fprintf(stderr, "Tape open error\n");
275 		askformount(index);
276 	}
277 	if (spcl.c_host[0] == '\0')
278 	{	gethostname(spcl.c_host, NAMELEN);
279 		spcl.c_level = 0;
280 		strcpy(spcl.c_filesys, "Tape has only been labelled");
281 		strcpy(spcl.c_dev, "???????????");
282 	}
283 	strcpy(spcl.c_label, createlabel(index));
284 	if (write(fd, (char *)&u_spcl, sizeof (u_spcl)) != sizeof (u_spcl))
285 	{	perror("Tape write error");
286 		exit(1);
287 	}
288 	rewind(fd);
289 	close(fd);
290 }
291 
292 /*
293  *	ask for a tape to be mounted
294  */
295 askformount(index)
296 {
297 	while (query("Mount tape `%s'\nReady to go? ", createlabel(index)) != 1);
298 }
299 
300 /*
301  *	ask yes/no question
302  *	return	1 on yes
303  *		0 on no
304  */
305 query(question, arg)
306 char	*question;
307 char *arg;
308 {
309 	char	replybuffer[64];
310 	int	back;
311 
312 	for(;;) {
313 		fprintf(stdout, question, arg);
314 		fflush(stdout);
315 		if (fgets(replybuffer, 63, stdin) == NULL) {
316 			if(ferror(stdin)) {
317 				clearerr(stdin);
318 				continue;
319 			}
320 		}
321 		else {
322 			qclean(replybuffer);
323 			if (strcmp(replybuffer, "yes") == 0 ||
324 			    strcmp(replybuffer, "y") == 0) {
325 				back = 1;
326 				goto done;
327 			}
328 			else
329 			if (strcmp(replybuffer, "no") == 0 ||
330 			    strcmp(replybuffer, "n") == 0) {
331 				if (query("Abort? "))
332 					labfatal("Aborting\n");
333 				back = 0;
334 				goto done;
335 			}
336 			else
337 				fprintf(stderr, "\"yes\" or \"no\" ONLY!\n");
338 		}
339 	}
340     done:
341 	return(back);
342 }
343 
344 qclean(ptr)
345 	register char *ptr;
346 {
347 	for (;*ptr; ptr++) {
348 		if (isupper(*ptr))
349 			*ptr = tolower(*ptr);
350 		if (*ptr == '\n') {
351 			*ptr = '\0';
352 			break;
353 		}
354 	}
355 }
356 
357 rewind(fd)
358 {
359 	struct mtop mtop;
360 
361 	if (dorew) {
362 		mtop.mt_op = MTOFFL;
363 		mtop.mt_count = 1;
364 		ioctl(fd, MTIOCTOP, &mtop);
365 	}
366 }
367 
368 /*
369  *	fatal error message routine
370  */
371 labfatal(fmt, a1, a2, a3, a4, a5)
372 	char	*fmt;
373 	int	a1, a2, a3, a4, a5;
374 {
375 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
376 	exit(1);
377 }
378 
379 /*
380  *	print the label from a tape
381  */
382 printlabel()
383 {
384 	register fd;
385 
386 	if ((fd = open(tape, 2)) < 0) {
387 		perror("Tape open error");
388 		exit(1);
389 	}
390 	if (read(fd, (char *)&u_spcl, sizeof u_spcl) < 0) {
391 		perror("Tape read");
392 		exit(1);
393 	}
394 	printf("Dump   date: %s", ctime(&spcl.c_date));
395 	printf("Dumped from: %s", ctime(&spcl.c_ddate));
396 	if (spcl.c_host[0] == '\0')
397 		return;
398 	printf("Level %d dump of %s on %s:%s\n",
399 		spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
400 	printf("Label: %s\n", spcl.c_label);
401 	printf("Volume %d of the dump, starting at inode %d\n",
402 			spcl.c_volume, spcl.c_inumber);
403 	close(fd);
404 }
405