Add label handling and rewind off line
[unix-history] / usr / src / local / ukc / dump / dumplabel.c
CommitLineData
da1346d6
PC
1#ifndef lint
2static char *sccsid = "@(#)dumplabel.c 1.1 (UKC) %G%";
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
45
46main(argc, argv)
47char **argv;
48{ register i;
49 register char *p;
50 while (--argc) {
51 argv++;
52 if (**argv == '-') {
53 for (p = *argv; *p; p++)
54 switch (*p) {
55
56 case 'f':
57 if (--argc > 0) {
58 argv++;
59 tape = *argv;
60 }
61 break;
62 case 'r':
63 dorew++; /* no rewind/offline */
64 break;
65 case 'l':
66 if (--argc > 0) {
67 argv++;
68 labfmt = *argv;
69 }
70 }
71 } else {
72 storelabelmap(arg);
73 for (i = 1; i <= labct; i++)
74 dolabel(i);
75 labct = 0;
76 }
77 }
78 if (tapecount == 0) {
79 if (labfmt) {
80 labct = 0;
81 dolabel(1); /* pretend a volume number of 1 */
82 } else
83 printlabel()
84 }
85 exit(0);
86}
87
88/*
89 * Store map list
90 * The map list
91 * allows a simple way to specify a range of tapes
92 * This generates a string which is inserted into the label format
93 * by use of an sprint operation
94 *
95 * The basic form here is:
96 * <string> a single string
97 * <string>,<string>,...... a list of strings
98 * <string>-<string> a range of strings
99 * where the string is `incremented'
100 * to generate a list
101 */
102storelabelmap(arg)
103 char *arg;
104{
105 register char *ss, *es;
106 register char *incbase, *incr;
107 register lastc;
108 char *labskip();
109 char *strstore();
110
111 /*
112 * Parse the argument looking for a single string
113 */
114 for (ss = arg; *ss; ss = es, labct++) {
115 es = labskip(ss);
116 lastc = *es; /* save last character */
117 *es++ = '\0'; /* make the first label into a string */
118 if (labct > LABMAX)
119 labfatal("Too many (> %d) tape labels specified\n", LABMAX);
120 labarg[labct++] = strstore(ss);
121
122 if (lastc == 0)
123 break; /* end of list */
124
125 if (lastc == '-') {
126 /*
127 * this gives a tape range
128 * increment the source number until it equals the final
129 * value
130 */
131 incbase = ss;
132 ss = es;
133 es = labskip(ss);
134 if (*es == '-')
135 labfatal("Range has the format <string>-<string>\n");
136 lastc = *es;
137 *es = '\0';
138 /*
139 * basic test the source string length must be equal to the
140 * end string length
141 */
142 if (strlen(incbase) != strlen(ss))
143 labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss);
144 labelrange(incbase, ss);
145 }
146 }
147}
148
149/*
150 * Expand a label range
151 */
152/* static */
153labelrange(startrange, endrange)
154 char *startrange, *endrange;
155{
156 register char *incr;
157 register int carry;
158
159
160 for (incr = startrange + strlen(startrange) - 1;
161 strcmp(startrange, endrange) != 0; ) {
162 /* start incrementing */
163 for (carry = 0; carry; ) {
164 if (isdigit(*incr)) {
165 if (*incr == '9') {
166 *incr = '0';
167 carry = 1;
168 } else
169 *incr++;
170 } else
171 if (isupper(*incr)) {
172 if (*incr == 'Z') {
173 *incr = 'A';
174 carry = 1;
175 } else
176 *incr++;
177 } else
178 if (islower(*incr)) {
179 if (*incr == 'z') {
180 *incr = 'a';
181 carry = 1;
182 } else
183 *incr++;
184 } else
185 labfatal("Problem with label map range spec - can only increment alphanumeric values\n");
186 if (carry) {
187 incr--;
188 if (incr < startrange)
189 labfatal("Problem with label map range spec - end of range reached\n");
190 }
191 }
192 if (labct > LABMAX)
193 labfatal("Too many (> %d) tape labels specified\n", LABMAX);
194 labarg[labct++] = strstore(startrange);
195
196 }
197}
198
199/*
200 * Store a string using malloc
201 */
202/* static */
203char *
204strstore(arg)
205 char *arg;
206{
207 register len = strlen(arg)+1;
208 register char *dest;
209 char *malloc();
210
211 dest = malloc(len);
212 if (dest == NULL)
213 labfatal("No memory for string storage\n");
214 bcopy(arg, dest, len);
215 return(dest);
216}
217
218/*
219 * Create a tape label from a volume number
220 */
221char *
222createlabel(volno)
223 int volno;
224{
225 static char buf[LBLSIZE+LBLSIZE];
226 static int lastvol;
227 char volbuf[8];
228 register char *arg;
229
230 if (userlabel == 0)
231 return ("none"); /* previous behaviour */
232
233 if (volno == lastvol) /* cache */
234 return(buf);
235 lastvol = volno;
236
237 if (labfmt == NULL)
238 labfmt = "%s";
239
240 if (labct == 0)
241 { (void) sprintf(volbuf, "%d", volno);
242 arg = volbuf;
243 }
244 else
245 arg = labarg[volno-1]; /* volumes run 1-> */
246 (void) sprintf(buf, labfmt, arg);
247 buf[LBLSIZE-1] = '\0'; /* Truncate to correct size */
248 return(buf);
249}
250
251/*
252 * skip forward looking for valid end of label characters
253 */
254char *
255labskip(str)
256register char *str;
257{ while (*str != ',' && *str != '-' && *str)
258 str++;
259 return (str);
260}
261
262/*
263 * do the actual labelling
264 */
265dolabel(index)
266{ register fd;
267
268 if (tapecount++)
269 askformount(index);
270
271 while ((fd = open(tape, 2)) < 0)
272 { fprintf(stderr, "Tape open error\n");
273 askformount(index);
274 }
275 strcpy(spcl.c_label, createlabel(index));
276 if (write(fd, (char *)&u_spcl, sizeof (u_spcl)) != sizeof (u_spcl))
277 { perror("Tape write error");
278 exit(1);
279 }
280 rewind(fd);
281 close(fd);
282}
283
284/*
285 * ask for a tape to be mounted
286 */
287askformount(index)
288{
289 while (query("Mount tape `%s'\nReady to go?", createlabel(index)) != 1);
290}
291
292/*
293 * ask yes/no question
294 * return 1 on yes
295 * 0 on no
296 */
297query(question, arg)
298char *question;
299char *arg;
300{
301 char replybuffer[64];
302 int back;
303
304 for(;;)
305 {
306 fprintf(stdout, question, arg);
307 fflush(stdout);
308 if (fgets(replybuffer, 63, stdin) == NULL)
309 { if(ferror(stdin))
310 { clearerr(stdin);
311 continue;
312 }
313 }
314 else
315 if ((strcmp(replybuffer, "yes\n") == 0) ||
316 (strcmp(replybuffer, "Yes\n") == 0))
317 {
318 back = 1;
319 goto done;
320 }
321 else
322 if ((strcmp(replybuffer, "no\n") == 0) ||
323 (strcmp(replybuffer, "No\n") == 0))
324 {
325 if (query("Abort? "))
326 labfatal("Aborting\n");
327 back = 0;
328 goto done;
329 }
330 else
331 fprintf(stderr, "\"Yes\" or \"No\" ONLY!\n");
332 }
333 done:
334 return(back);
335}
336
337rewind(fd)
338{
339 struct mtop mtop;
340 if (dorew)
341 { mtop.mt_op = MTOFFL;
342 mtop.mt_count = 1;
343 ioctl(fd, MTIOCTOP, &mtop);
344 }
345}
346
347/*
348 * fatal error message routine
349 */
350labfatal(fmt, a1, a2, a3, a4, a5)
351char *fmt;
352int a1, a2, a3, a4, a5;
353{ fprintf(stderr, fmt, a1, a2, a3, a4, a5);
354 exit(1);
355}
356
357/*
358 * print the label from a tape
359 */
360printlabel()
361{
362 register fd;
363
364 if ((fd = open(tape, 2)) < 0)
365 { perror("Tape open error");
366 exit(1);
367 }
368 if (read(fd, (char *)&u_spcl, sizeof u_spcl) < 0)
369 { perror("Tape read");
370 exit(1);
371 }
372 printf("%s\n", spcl.c_label);
373 close(fd);
374}