132027Spc #ifndef lint
2*32045Spc static char *sccsid = "@(#)dumplabel.c 1.3 (UKC) 08/11/87";
332027Spc #endif not lint
432027Spc /***
532027Spc
632027Spc * program name:
732027Spc dumplabel.c
832027Spc * function:
932027Spc prints the label from a header
1032027Spc writes a dummy dump header at the start of a tape
1132027Spc Doesn't do any checksum
1232027Spc * switches:
1332027Spc -f <tapename>
1432027Spc -r rewind/offline each tape
1532027Spc -l label format
1632027Spc followed by list of tape labels in the same format at given to the
1732027Spc locally modified dump program
1832027Spc if no tape labels are given print the details on the start of a tape
1932027Spc * libraries used:
2032027Spc standard
2132027Spc * compile time parameters:
2232027Spc cc -o dumplabel dumplabel.c
2332027Spc * history:
2432027Spc Written August 1987 Peter Collinson UKC
2532027Spc
2632027Spc ***/
2732027Spc #include "dump.h"
2832027Spc #include <sys/ioctl.h>
2932027Spc #include <sys/mtio.h>
3032027Spc
3132027Spc #define LABMAX 100 /* get space for 100 */
3232027Spc
3332027Spc char *labarg[LABMAX]; /* vector of map entries */
3432027Spc
3532027Spc char *labfmt; /* format for tape label */
3632027Spc
3732027Spc int labct; /* number of entries */
3832027Spc /* if zero then no labels used */
3932027Spc
4032027Spc char *tape = "/dev/rmt8";
4132027Spc
4232027Spc int dorew; /* set if rewind offline on exit */
4332027Spc int tapecount; /* number of tapes dealt with */
4432027Spc
4532029Spc char *index();
4632027Spc
main(argc,argv)4732027Spc main(argc, argv)
4832027Spc char **argv;
4932027Spc { register i;
5032027Spc register char *p;
5132027Spc while (--argc) {
5232027Spc argv++;
5332027Spc if (**argv == '-') {
5432027Spc for (p = *argv; *p; p++)
5532027Spc switch (*p) {
5632027Spc
5732027Spc case 'f':
5832027Spc if (--argc > 0) {
5932027Spc argv++;
6032027Spc tape = *argv;
6132027Spc }
6232027Spc break;
6332027Spc case 'r':
6432027Spc dorew++; /* no rewind/offline */
6532027Spc break;
6632027Spc case 'l':
6732027Spc if (--argc > 0) {
6832027Spc argv++;
6932027Spc labfmt = *argv;
7032027Spc }
7132027Spc }
7232027Spc } else {
7332029Spc storelabelmap(*argv);
7432029Spc if (labfmt && labct)
7532029Spc if (index(labfmt, '%') == NULL)
7632029Spc fprintf(stderr, "Warning - no format specifier (%%s) found in -l argument\n");
7732027Spc for (i = 1; i <= labct; i++)
7832027Spc dolabel(i);
7932027Spc labct = 0;
8032027Spc }
8132027Spc }
8232027Spc if (tapecount == 0) {
8332027Spc if (labfmt) {
8432027Spc labct = 0;
8532027Spc dolabel(1); /* pretend a volume number of 1 */
8632027Spc } else
8732029Spc printlabel();
8832027Spc }
8932027Spc exit(0);
9032027Spc }
9132027Spc
9232027Spc /*
9332027Spc * Store map list
9432027Spc * The map list
9532027Spc * allows a simple way to specify a range of tapes
9632027Spc * This generates a string which is inserted into the label format
9732027Spc * by use of an sprint operation
9832027Spc *
9932027Spc * The basic form here is:
10032027Spc * <string> a single string
10132027Spc * <string>,<string>,...... a list of strings
10232027Spc * <string>-<string> a range of strings
10332027Spc * where the string is `incremented'
10432027Spc * to generate a list
10532027Spc */
storelabelmap(arg)10632027Spc storelabelmap(arg)
10732027Spc char *arg;
10832027Spc {
10932027Spc register char *ss, *es;
11032027Spc register char *incbase, *incr;
11132027Spc register lastc;
11232027Spc char *labskip();
11332027Spc char *strstore();
11432027Spc
11532027Spc /*
11632027Spc * Parse the argument looking for a single string
11732027Spc */
11832029Spc for (ss = arg; *ss; ss = es) {
11932027Spc es = labskip(ss);
12032027Spc lastc = *es; /* save last character */
12132027Spc *es++ = '\0'; /* make the first label into a string */
12232027Spc if (labct > LABMAX)
12332027Spc labfatal("Too many (> %d) tape labels specified\n", LABMAX);
12432029Spc if (*ss == '\0')
12532029Spc labfatal("Zero length label found\n");
12632027Spc labarg[labct++] = strstore(ss);
12732027Spc
12832027Spc if (lastc == 0)
12932027Spc break; /* end of list */
13032027Spc
13132027Spc if (lastc == '-') {
13232027Spc /*
13332027Spc * this gives a tape range
13432027Spc * increment the source number until it equals the final
13532027Spc * value
13632027Spc */
13732027Spc incbase = ss;
13832027Spc ss = es;
13932027Spc es = labskip(ss);
14032027Spc if (*es == '-')
14132027Spc labfatal("Range has the format <string>-<string>\n");
14232027Spc lastc = *es;
14332029Spc if (lastc)
14432029Spc *es++ = '\0';
14532027Spc /*
14632027Spc * basic test the source string length must be equal to the
14732027Spc * end string length
14832027Spc */
14932027Spc if (strlen(incbase) != strlen(ss))
15032027Spc labfatal("strlen(\"%s\") != strlen(\"%s\")\n", incbase, ss);
15132027Spc labelrange(incbase, ss);
15232027Spc }
15332027Spc }
15432027Spc }
15532027Spc
15632027Spc /*
15732027Spc * Expand a label range
15832027Spc */
15932027Spc /* static */
labelrange(startrange,endrange)16032027Spc labelrange(startrange, endrange)
16132027Spc char *startrange, *endrange;
16232027Spc {
16332027Spc register char *incr;
16432027Spc register int carry;
16532027Spc
16632027Spc
16732027Spc for (incr = startrange + strlen(startrange) - 1;
16832027Spc strcmp(startrange, endrange) != 0; ) {
16932027Spc /* start incrementing */
17032029Spc carry = 0;
17132029Spc do {
17232027Spc if (isdigit(*incr)) {
17332027Spc if (*incr == '9') {
17432027Spc *incr = '0';
17532027Spc carry = 1;
17632027Spc } else
17732029Spc (*incr)++;
17832027Spc } else
17932027Spc if (isupper(*incr)) {
18032027Spc if (*incr == 'Z') {
18132027Spc *incr = 'A';
18232027Spc carry = 1;
18332027Spc } else
18432029Spc (*incr)++;
18532027Spc } else
18632027Spc if (islower(*incr)) {
18732027Spc if (*incr == 'z') {
18832027Spc *incr = 'a';
18932027Spc carry = 1;
19032027Spc } else
19132029Spc (*incr)++;
19232027Spc } else
19332027Spc labfatal("Problem with label map range spec - can only increment alphanumeric values\n");
19432027Spc if (carry) {
19532027Spc incr--;
19632027Spc if (incr < startrange)
19732027Spc labfatal("Problem with label map range spec - end of range reached\n");
19832027Spc }
19932029Spc } while (carry);
20032029Spc
20132027Spc if (labct > LABMAX)
20232027Spc labfatal("Too many (> %d) tape labels specified\n", LABMAX);
20332027Spc labarg[labct++] = strstore(startrange);
20432027Spc
20532027Spc }
20632027Spc }
20732027Spc
20832027Spc /*
20932027Spc * Store a string using malloc
21032027Spc */
21132027Spc /* static */
21232027Spc char *
strstore(arg)21332027Spc strstore(arg)
21432027Spc char *arg;
21532027Spc {
21632027Spc register len = strlen(arg)+1;
21732027Spc register char *dest;
21832027Spc char *malloc();
21932027Spc
22032027Spc dest = malloc(len);
22132027Spc if (dest == NULL)
22232027Spc labfatal("No memory for string storage\n");
22332027Spc bcopy(arg, dest, len);
22432027Spc return(dest);
22532027Spc }
22632027Spc
22732027Spc /*
22832027Spc * Create a tape label from a volume number
22932027Spc */
23032027Spc char *
createlabel(volno)23132027Spc createlabel(volno)
23232027Spc int volno;
23332027Spc {
23432027Spc static char buf[LBLSIZE+LBLSIZE];
23532027Spc char volbuf[8];
23632027Spc register char *arg;
23732027Spc
23832027Spc
23932027Spc if (labfmt == NULL)
24032027Spc labfmt = "%s";
24132027Spc
24232027Spc if (labct == 0)
24332027Spc { (void) sprintf(volbuf, "%d", volno);
24432027Spc arg = volbuf;
24532027Spc }
24632027Spc else
24732027Spc arg = labarg[volno-1]; /* volumes run 1-> */
24832027Spc (void) sprintf(buf, labfmt, arg);
24932027Spc buf[LBLSIZE-1] = '\0'; /* Truncate to correct size */
25032027Spc return(buf);
25132027Spc }
25232027Spc
25332027Spc /*
25432027Spc * skip forward looking for valid end of label characters
25532027Spc */
25632027Spc char *
labskip(str)25732027Spc labskip(str)
25832027Spc register char *str;
25932027Spc { while (*str != ',' && *str != '-' && *str)
26032027Spc str++;
26132027Spc return (str);
26232027Spc }
26332027Spc
26432027Spc /*
26532027Spc * do the actual labelling
26632027Spc */
dolabel(index)26732027Spc dolabel(index)
26832027Spc { register fd;
26932027Spc
27032029Spc tapecount++;
27132029Spc askformount(index);
27232027Spc
27332027Spc while ((fd = open(tape, 2)) < 0)
27432027Spc { fprintf(stderr, "Tape open error\n");
27532027Spc askformount(index);
27632027Spc }
277*32045Spc if (spcl.c_host[0] == '\0')
278*32045Spc { gethostname(spcl.c_host, NAMELEN);
279*32045Spc spcl.c_level = 0;
280*32045Spc strcpy(spcl.c_filesys, "Tape has only been labelled");
281*32045Spc strcpy(spcl.c_dev, "???????????");
282*32045Spc }
28332027Spc strcpy(spcl.c_label, createlabel(index));
28432027Spc if (write(fd, (char *)&u_spcl, sizeof (u_spcl)) != sizeof (u_spcl))
28532027Spc { perror("Tape write error");
28632027Spc exit(1);
28732027Spc }
28832027Spc rewind(fd);
28932027Spc close(fd);
29032027Spc }
29132027Spc
29232027Spc /*
29332027Spc * ask for a tape to be mounted
29432027Spc */
askformount(index)29532027Spc askformount(index)
29632027Spc {
29732029Spc while (query("Mount tape `%s'\nReady to go? ", createlabel(index)) != 1);
29832027Spc }
29932027Spc
30032027Spc /*
30132027Spc * ask yes/no question
30232027Spc * return 1 on yes
30332027Spc * 0 on no
30432027Spc */
query(question,arg)30532027Spc query(question, arg)
30632027Spc char *question;
30732027Spc char *arg;
30832027Spc {
30932027Spc char replybuffer[64];
31032027Spc int back;
31132027Spc
31232029Spc for(;;) {
31332027Spc fprintf(stdout, question, arg);
31432027Spc fflush(stdout);
31532029Spc if (fgets(replybuffer, 63, stdin) == NULL) {
31632029Spc if(ferror(stdin)) {
31732029Spc clearerr(stdin);
31832027Spc continue;
31932027Spc }
32032027Spc }
32132029Spc else {
32232029Spc qclean(replybuffer);
32332029Spc if (strcmp(replybuffer, "yes") == 0 ||
32432029Spc strcmp(replybuffer, "y") == 0) {
32532029Spc back = 1;
32632029Spc goto done;
32732029Spc }
32832029Spc else
32932029Spc if (strcmp(replybuffer, "no") == 0 ||
33032029Spc strcmp(replybuffer, "n") == 0) {
33132029Spc if (query("Abort? "))
33232029Spc labfatal("Aborting\n");
33332029Spc back = 0;
33432029Spc goto done;
33532029Spc }
33632029Spc else
33732029Spc fprintf(stderr, "\"yes\" or \"no\" ONLY!\n");
33832027Spc }
33932027Spc }
34032027Spc done:
34132027Spc return(back);
34232027Spc }
34332027Spc
qclean(ptr)34432029Spc qclean(ptr)
34532029Spc register char *ptr;
34632029Spc {
34732029Spc for (;*ptr; ptr++) {
34832029Spc if (isupper(*ptr))
34932029Spc *ptr = tolower(*ptr);
35032029Spc if (*ptr == '\n') {
35132029Spc *ptr = '\0';
35232029Spc break;
35332029Spc }
35432029Spc }
35532029Spc }
35632029Spc
rewind(fd)35732027Spc rewind(fd)
35832027Spc {
35932027Spc struct mtop mtop;
36032029Spc
36132029Spc if (dorew) {
36232029Spc mtop.mt_op = MTOFFL;
36332027Spc mtop.mt_count = 1;
36432027Spc ioctl(fd, MTIOCTOP, &mtop);
36532027Spc }
36632027Spc }
36732027Spc
36832027Spc /*
36932027Spc * fatal error message routine
37032027Spc */
labfatal(fmt,a1,a2,a3,a4,a5)37132027Spc labfatal(fmt, a1, a2, a3, a4, a5)
37232029Spc char *fmt;
37332029Spc int a1, a2, a3, a4, a5;
37432029Spc {
37532029Spc fprintf(stderr, fmt, a1, a2, a3, a4, a5);
37632027Spc exit(1);
37732027Spc }
37832027Spc
37932027Spc /*
38032027Spc * print the label from a tape
38132027Spc */
printlabel()38232027Spc printlabel()
38332027Spc {
38432027Spc register fd;
38532027Spc
38632029Spc if ((fd = open(tape, 2)) < 0) {
38732029Spc perror("Tape open error");
38832027Spc exit(1);
38932027Spc }
39032029Spc if (read(fd, (char *)&u_spcl, sizeof u_spcl) < 0) {
39132029Spc perror("Tape read");
39232027Spc exit(1);
39332027Spc }
394*32045Spc printf("Dump date: %s", ctime(&spcl.c_date));
395*32045Spc printf("Dumped from: %s", ctime(&spcl.c_ddate));
396*32045Spc if (spcl.c_host[0] == '\0')
397*32045Spc return;
398*32045Spc printf("Level %d dump of %s on %s:%s\n",
399*32045Spc spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
400*32045Spc printf("Label: %s\n", spcl.c_label);
401*32045Spc printf("Volume %d of the dump, starting at inode %d\n",
402*32045Spc spcl.c_volume, spcl.c_inumber);
40332027Spc close(fd);
40432027Spc }
405