ANSIfication; bug report 4.3BSD/bin/223
[unix-history] / usr / src / local / ukc / dump / dumplabel.c
CommitLineData
da1346d6 1#ifndef lint
224c2d4c 2static char *sccsid = "@(#)dumplabel.c 1.3 (UKC) %G%";
da1346d6
PC
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
33char *labarg[LABMAX]; /* vector of map entries */
34
35char *labfmt; /* format for tape label */
36
37int labct; /* number of entries */
38 /* if zero then no labels used */
39
40char *tape = "/dev/rmt8";
41
42int dorew; /* set if rewind offline on exit */
43int tapecount; /* number of tapes dealt with */
44
43561fec 45char *index();
da1346d6
PC
46
47main(argc, argv)
48char **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 {
43561fec
PC
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");
da1346d6
PC
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
43561fec 87 printlabel();
da1346d6
PC
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 */
106storelabelmap(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 */
43561fec 118 for (ss = arg; *ss; ss = es) {
da1346d6
PC
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);
43561fec
PC
124 if (*ss == '\0')
125 labfatal("Zero length label found\n");
da1346d6
PC
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;
43561fec
PC
143 if (lastc)
144 *es++ = '\0';
da1346d6
PC
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 */
160labelrange(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 */
43561fec
PC
170 carry = 0;
171 do {
da1346d6
PC
172 if (isdigit(*incr)) {
173 if (*incr == '9') {
174 *incr = '0';
175 carry = 1;
176 } else
43561fec 177 (*incr)++;
da1346d6
PC
178 } else
179 if (isupper(*incr)) {
180 if (*incr == 'Z') {
181 *incr = 'A';
182 carry = 1;
183 } else
43561fec 184 (*incr)++;
da1346d6
PC
185 } else
186 if (islower(*incr)) {
187 if (*incr == 'z') {
188 *incr = 'a';
189 carry = 1;
190 } else
43561fec 191 (*incr)++;
da1346d6
PC
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 }
43561fec
PC
199 } while (carry);
200
da1346d6
PC
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 */
212char *
213strstore(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 */
230char *
231createlabel(volno)
232 int volno;
233{
234 static char buf[LBLSIZE+LBLSIZE];
da1346d6
PC
235 char volbuf[8];
236 register char *arg;
237
da1346d6
PC
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 */
256char *
257labskip(str)
258register char *str;
259{ while (*str != ',' && *str != '-' && *str)
260 str++;
261 return (str);
262}
263
264/*
265 * do the actual labelling
266 */
267dolabel(index)
268{ register fd;
269
43561fec
PC
270 tapecount++;
271 askformount(index);
da1346d6
PC
272
273 while ((fd = open(tape, 2)) < 0)
274 { fprintf(stderr, "Tape open error\n");
275 askformount(index);
276 }
224c2d4c
PC
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 }
da1346d6
PC
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 */
295askformount(index)
296{
43561fec 297 while (query("Mount tape `%s'\nReady to go? ", createlabel(index)) != 1);
da1346d6
PC
298}
299
300/*
301 * ask yes/no question
302 * return 1 on yes
303 * 0 on no
304 */
305query(question, arg)
306char *question;
307char *arg;
308{
309 char replybuffer[64];
310 int back;
311
43561fec 312 for(;;) {
da1346d6
PC
313 fprintf(stdout, question, arg);
314 fflush(stdout);
43561fec
PC
315 if (fgets(replybuffer, 63, stdin) == NULL) {
316 if(ferror(stdin)) {
317 clearerr(stdin);
da1346d6
PC
318 continue;
319 }
320 }
43561fec
PC
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");
da1346d6 338 }
da1346d6
PC
339 }
340 done:
341 return(back);
342}
343
43561fec
PC
344qclean(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
da1346d6
PC
357rewind(fd)
358{
359 struct mtop mtop;
43561fec
PC
360
361 if (dorew) {
362 mtop.mt_op = MTOFFL;
da1346d6
PC
363 mtop.mt_count = 1;
364 ioctl(fd, MTIOCTOP, &mtop);
365 }
366}
367
368/*
369 * fatal error message routine
370 */
371labfatal(fmt, a1, a2, a3, a4, a5)
43561fec
PC
372 char *fmt;
373 int a1, a2, a3, a4, a5;
374{
375 fprintf(stderr, fmt, a1, a2, a3, a4, a5);
da1346d6
PC
376 exit(1);
377}
378
379/*
380 * print the label from a tape
381 */
382printlabel()
383{
384 register fd;
385
43561fec
PC
386 if ((fd = open(tape, 2)) < 0) {
387 perror("Tape open error");
da1346d6
PC
388 exit(1);
389 }
43561fec
PC
390 if (read(fd, (char *)&u_spcl, sizeof u_spcl) < 0) {
391 perror("Tape read");
da1346d6
PC
392 exit(1);
393 }
224c2d4c
PC
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);
da1346d6
PC
403 close(fd);
404}