# /* * o d . c */ /*)BUILD $(TKBOPTIONS) = { TASK = ...ODX } */ #ifdef DOCUMENTATION title od Octal Dump index od Octal Dump synopsis od [-options] [-f blocknumber] [-l blocknumber] file description od dumps binary files in human-readable format. The following options are defined: .lm +8 .s.i -8;-a Dump ASCII characters .s.i -8;-b Dump octal bytes .s.i -8;-f _# Set first record, default is 0 .s.i -8;-l _# Set last record, default is EOF .s.i -8;-u Dump by block, even if record-oriented .s.i -8;-w Dump octal words .s.i -8;-x Dump hexadecimal bytes .s.i -8;-5 Dump radix 50 words. .s.lm -8 If no format options are selected, od dumps records by words "-w". .s On RSX, od defaults to record mode dumps. Use the -u switch to force a block mode dump. diagnostics .lm +8 .s.i -8;"File name": Cannot open .s.i -8;Usage ... .lm -8 bugs od is heavily dependent on Decus C libraries. It will not run correctly on vax-11 C. If compiled with the RT11 library, it cannot read "attributed" files on RSTS/E. author David Conroy #endif #include #define EOS 0 #define FALSE 0 #define TRUE 1 #ifdef rt11 #define RECORD unsigned int #define ZERO 0 #define HUGE 32767 #define BSIZ 512 #endif #ifdef rsx #define RECORD long #define ZERO 0L #define HUGE 04000000L /* Max block on ODS-1 */ #define BSIZ 512 #endif #ifdef vms #define RECORD long #define ZERO 0l #define HUGE 04000000L #define BSIZ 512 #endif int aflag = FALSE; int bflag = FALSE; int fflag = FALSE; int uflag = FALSE; int wflag = FALSE; int xflag = FALSE; int max_size; char *filename; char *buf = NULL; FILE *fd; RECORD fbn = ZERO; RECORD lbn = HUGE; #ifdef rsx /* * The following are offsets (F_xxx) and values (R_xxx) in the FDB */ extern char *F_RTYP; /* record type */ extern char *F_RATT; /* record attributes */ extern char *F_RSIZ; /* record size word */ extern char *F_SEQN; /* printfile fixed header word */ extern char *R_FIX; /* in F.RTYP for fixed-length */ extern char *R_SEQ; /* in F.RTYP for printfile */ int seqflag = FALSE; /* Set to test for sequence */ #endif main(argc, argv) char *argv[]; { register int i, c; register char *p; char *bp; filename = NULL; for(i=1; i= argc) usage(); fbn = atoi(argv[i]); break; case 'l': if(++i >= argc) usage(); lbn = atoi(argv[i]); break; default: usage(); } } } else if(filename != NULL) usage(); /* Two files to dump */ else filename = p; } if(filename == NULL) usage(); if(lbn < fbn) usage(); if(!aflag && !bflag && !fflag && !wflag && !xflag) ++wflag; if((fd = fopen(filename, "ru")) == NULL) cant(filename); #ifdef rsx max_size = fd->io_rbsz; bp = "Record"; /* * If the file is record oriented, and the user set the -u * (block mode) switch, the attributes in the FDB are fudged to * make the FCS routines think it is an R.FIX file with R.SIZE=512 * and no carriage control attributes. This makes it dump a record * file in block format, so you can see all the RCW's, etc. * * If a record-oriented dump is being done, set the sequence-format * flag to identify printfile format. */ if (uflag && !frec(fd)) { bp = "Block"; max_size = BSIZ; /* * Set to fixed blocked, no attributes, 512 byte records */ fd->io_fdb[(int) &F_RTYP] = (int) &R_FIX; fd->io_fdb[(int) &F_RATT] = 0; *((int *) &fd->io_fdb[(int) &F_RSIZ]) = BSIZ; seqflag = FALSE; /* Never do sequencing */ } else seqflag = ((fd->io_fdb[(int) &F_RTYP] & 0377) == (int) &R_SEQ); if ((buf = malloc(max_size)) == NULL) error("Can't allocate record buffer of %d bytes\n", max_size); #endif #ifdef rt11 /* * Rt11 is always a block mode dump */ max_size = BSIZ; if ((buf = malloc(BSIZ)) == NULL) error("Can't allocate block buffer of %d bytes\n", BSIZ); bp = "Block"; #endif dump(bp); } /* * Do the dump. * `bp' is the banner string * (either "block" or "record"). */ dump(bp) char *bp; { register int n; RECORD rn; long place; long ftell(); rn = ZERO; while(rn < fbn) { #ifdef rsx fget(buf, max_size, fd); #endif #ifdef rt11 fread(buf, 1, max_size, fd); #endif if(feof(fd)) { perror(filename); return; } rn++; } while(rn <= lbn) { place = ftell(fd); #ifdef rsx n = fget(buf, max_size, fd); if(feof(fd)) { perror(filename); return; } #endif #ifdef rt11 n = fread(buf, 1, max_size, fd); if(feof(fd)) { perror(filename); return; } printf("\n** %s %d at %ld. [%06o %06o] length = %d. bytes\n", bp, rn++, place, place, n); #endif #ifdef rsx printf( "\n** %s %ld: length = %d bytes, VBN = %07lo, block offset = %03lo\n", bp, rn++, n, place/512L, place%512L); if (seqflag) { printf("** record sequence number = %u. [%04x hex]\n", *((int *) &fd->io_fdb[(int) &F_SEQN]), *((int *) &fd->io_fdb[(int) &F_SEQN])); } #endif printf("\n"); format(buf, n); } } /* * Dump out an `n' byte * item according to the flags * set by the user. */ format(ap, n) char *ap; { register int *wp; register char *bp; register int i; int o, of, nb, c; char ab[3], *fmt; if(!bflag && !wflag && xflag) fmt = "%04x "; else fmt = "%06o"; o = 0; while(n) { nb = min(16, n); of = 1; if(wflag) { printf(fmt, o); of = 0; printf(" w"); wp = ap; i = (nb & 017776)/2; /* hack odd size rec */ while(i--) printf(" %06o", *wp++); putchar('\n'); } if(aflag) { if(of) { printf(fmt, o); of = 0; } else printf(" "); printf(" a"); bp = ap; i = nb; while(i--) { c = *bp++ & 0377; if(c<' ' || c>'~') printf(" %03o", c); else printf(" %c", c); } putchar('\n'); } if(bflag) { if(of) { printf(fmt, o); of = 0; } else printf(" "); printf(" b"); bp = ap; i = nb; while(i--) printf(" %03o", *bp++ & 0377); putchar('\n'); } if(fflag) { if(of) { printf(fmt, o); of = 0; } else printf(" "); printf(" 5"); wp = ap; i = nb/2; while(i--) { r50toa(ab, wp++, 1); printf(" %.3s", ab); } putchar('\n'); } if(xflag) { if(of) printf(fmt, o); else printf(" "); printf(" x"); bp = ap; i = nb; while(i--) printf(" %02x", *bp++ & 0377); putchar('\n'); } o += 16; ap += 16; n -= nb; } } /* * Compute the minimum of * two numbers. * Should be in the library. */ min(a, b) { if(a < b) return(a); return(b); } /* * Cannot open diagnostic. * Just exit. */ cant(p) char *p; { fprintf(stderr, "%s: cannot open\n", p); exit(1); } /* * Usage diagnostic. * Just exit. */ usage() { fprintf(stderr, "Usage: dump [-5abrwx] [-f bn] [-l bn] file\n"); exit(1); }