[6] | 1 | /* |
---|
| 2 | * $Source: /afs/dev.mit.edu/source/repository/athena/bin/ansi/ansi.c,v $ |
---|
| 3 | * $Author: builder $ |
---|
| 4 | * $Locker: $ |
---|
| 5 | * $Header: /afs/dev.mit.edu/source/repository/athena/bin/ansi/ansi.c,v 1.1 1985-04-12 15:28:23 builder Exp $ |
---|
| 6 | */ |
---|
| 7 | |
---|
| 8 | #ifndef lint |
---|
| 9 | static char *rcsid_ansi_c = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/ansi/ansi.c,v 1.1 1985-04-12 15:28:23 builder Exp $"; |
---|
| 10 | #endif lint |
---|
| 11 | |
---|
| 12 | #include <stdio.h> |
---|
| 13 | /* Rewritten almost entirely from stolen MIT original by Jim Gettys, |
---|
| 14 | The Institute for Advanced Study, Princeton, NJ. */ |
---|
| 15 | |
---|
| 16 | /* this program written to read Ansi labeled tapes produced by Vax/VMS 2.5*/ |
---|
| 17 | /* results on other tapes/or versions of VMS 3.0 or later not guaranteed.*/ |
---|
| 18 | |
---|
| 19 | /* note that the variable record file may not be what you want for fortran */ |
---|
| 20 | /* written unformatted files, which add a 2 byte segment code at the start*/ |
---|
| 21 | /* of each record. The accompanying program "unseg" will create Unix fortran*/ |
---|
| 22 | /* style files from a VMS fortran segmented file. Note that VMS creates these*/ |
---|
| 23 | /* segmented files by default.*/ |
---|
| 24 | |
---|
| 25 | #define BINARY 0 /*binary files are copied in unchanged*/ |
---|
| 26 | /* .exe or Eunice stream files*/ |
---|
| 27 | #define CRLF 1 /*insert new line after each record*/ |
---|
| 28 | /* typical .for, .lis etc text files*/ |
---|
| 29 | #define FORTRAN 2 /*fortran carriage control interpretation*/ |
---|
| 30 | /* output of fortran programs*/ |
---|
| 31 | #define VARIABLE 3 /*read in variable length recs, transcribe */ |
---|
| 32 | /* to unix fortran style variable records*/ |
---|
| 33 | /* sequential fortran (unformatted) or .obj */ |
---|
| 34 | /* files, transcribed to Unix fortran files*/ |
---|
| 35 | |
---|
| 36 | int vnos = 1; /*restore version numbers of files*/ |
---|
| 37 | int verbose = 0; |
---|
| 38 | int superverbose = 0; /*super verbose mode*/ |
---|
| 39 | int fbinary = 0; /*force binary input mode, debugging*/ |
---|
| 40 | int list = 0; /*listing mode*/ |
---|
| 41 | |
---|
| 42 | /* the following structure definitions generated in reference to DEC VAX/VMS |
---|
| 43 | magnetic tape user's guide, appendix a */ |
---|
| 44 | |
---|
| 45 | int fbsize; /*file block size determined from tape*/ |
---|
| 46 | char cbuffer[100]; /*numeric conversion buffer*/ |
---|
| 47 | |
---|
| 48 | struct volume1 { |
---|
| 49 | char v_lid[3]; /*label id*/ |
---|
| 50 | char v_num; /*label number*/ |
---|
| 51 | char v_id[6]; /*volume id*/ |
---|
| 52 | char v_acc; /*volume access*/ |
---|
| 53 | char v_res1[26]; /*reserved space*/ |
---|
| 54 | char v_owner[13]; /*owner identifier*/ |
---|
| 55 | char v_std; /*Digital Standard*/ |
---|
| 56 | char v_res2[28]; /*reseved space*/ |
---|
| 57 | char v_lstd; /*label Standard Version 1 (3)*/ |
---|
| 58 | } vol1; |
---|
| 59 | |
---|
| 60 | struct header1 { /*hdr1 record format*/ |
---|
| 61 | char h1_lid[3]; /*label id*/ |
---|
| 62 | char h1_num; /*label number (1)*/ |
---|
| 63 | char h1_fname[17]; /*file identifier*/ |
---|
| 64 | char h1_fset[6]; /*file set id*/ |
---|
| 65 | char h1_fsec[4]; /*file section number*/ |
---|
| 66 | char h1_seqno[4]; /*file sequence number*/ |
---|
| 67 | char h1_genno[4]; /*generation number*/ |
---|
| 68 | char h1_gverno[2]; /*version of generation number*/ |
---|
| 69 | char h1_credate[6]; /*creation date*/ |
---|
| 70 | char h1_exdate[6]; /*expiration date*/ |
---|
| 71 | char h1_access; /*file accessability*/ |
---|
| 72 | char h1_blcount[6]; /*block count (always zero from DEC on hdr1*/ |
---|
| 73 | char h1_syscode[13]; /*system code, should be DECFILE11A*/ |
---|
| 74 | char h1_res1[7]; /*reserved space*/ |
---|
| 75 | } hdr1; |
---|
| 76 | struct header2 { /*hdr2 record format*/ |
---|
| 77 | char h2_lid[3]; /*label id*/ |
---|
| 78 | char h2_num; /*label number(should be a 2)*/ |
---|
| 79 | char h2_format; /*record format F is fixed, D is Variable*/ |
---|
| 80 | char h2_bsize[5]; /*maximum number of chars/block*/ |
---|
| 81 | char h2_rlength[5]; /*record length fixed, max length variable*/ |
---|
| 82 | char h2_flag; /*flag for RMS cruft*/ |
---|
| 83 | char h2_rmscrud1[20]; /*for VMS 2.0 and earlier, contains RMS Crud*/ |
---|
| 84 | char h2_form; /*forms control, A means fortran, |
---|
| 85 | M imbedded control, space means crlf needed*/ |
---|
| 86 | char h2_morerms[13]; /*more rms stuff*/ |
---|
| 87 | char h2_buffoff[2]; /*buffer offset, should be 00*/ |
---|
| 88 | char h2_res1[28]; /*reserved for future use*/ |
---|
| 89 | } hdr2; |
---|
| 90 | |
---|
| 91 | char buffer[32768]; /* buffer for raw reads from magtape */ |
---|
| 92 | char nl[] = "\n"; /* carriage control characters */ |
---|
| 93 | char ff[] = "\f"; |
---|
| 94 | char cr[] = "\r"; |
---|
| 95 | |
---|
| 96 | main(argc,argv) |
---|
| 97 | int argc; |
---|
| 98 | char *argv[]; |
---|
| 99 | { register int i; |
---|
| 100 | register char *p; |
---|
| 101 | int version,genno,genver; |
---|
| 102 | char filename[25]; /* recreated file name */ |
---|
| 103 | int bf,ef = argc; /* beginning and ending files*/ |
---|
| 104 | char *s; |
---|
| 105 | char *tfile = "/dev/rmt8"; /* pointer to tape to open */ |
---|
| 106 | int match = 0; /* file name match with argument list*/ |
---|
| 107 | int first; |
---|
| 108 | int tape,file,bitbucket,c,ftype; |
---|
| 109 | for(i = 0; i < argc; i++) { |
---|
| 110 | if(argv[i][0] != '-') continue; |
---|
| 111 | bf = i + 1; /* save last argument found*/ |
---|
| 112 | for(s = argv[i] + 1; *s != '\0'; s++) |
---|
| 113 | switch(*s) { |
---|
| 114 | case 0: |
---|
| 115 | break; |
---|
| 116 | case 'b': |
---|
| 117 | fbinary = 1; |
---|
| 118 | printf("ansi: warning, binary input forced.\n"); |
---|
| 119 | break; |
---|
| 120 | case 'v': |
---|
| 121 | verbose = 1; |
---|
| 122 | break; |
---|
| 123 | case 's': |
---|
| 124 | superverbose = 1; |
---|
| 125 | verbose = 1; |
---|
| 126 | break; |
---|
| 127 | case 'f': |
---|
| 128 | bf += 1; /*skip drive*/ |
---|
| 129 | tfile = argv[i + 1]; |
---|
| 130 | printf("file %s\n",argv[1]); |
---|
| 131 | break; |
---|
| 132 | case 'i': |
---|
| 133 | vnos = 0; |
---|
| 134 | break; |
---|
| 135 | case 'l': |
---|
| 136 | list = 1; |
---|
| 137 | verbose = 1; |
---|
| 138 | break; |
---|
| 139 | default: |
---|
| 140 | fprintf(stderr, |
---|
| 141 | "usage: ansi -[bfilsv tape files]\n"); |
---|
| 142 | exit(1); |
---|
| 143 | } |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | bitbucket = open("/dev/null",1); |
---|
| 147 | tape = open(tfile,0); /* acquire the tape drive */ |
---|
| 148 | if (tape == -1) { |
---|
| 149 | printf("Can't open %s\n",tfile); |
---|
| 150 | exit(-1); |
---|
| 151 | } |
---|
| 152 | |
---|
| 153 | if ((c=read(tape,&vol1,80)) != 80) { /* read in volume label */ |
---|
| 154 | printf("Error in reading volume label.\n"); |
---|
| 155 | exit(-1); |
---|
| 156 | } |
---|
| 157 | if(verbose) printf("Volume label found was %6.6s.\n",vol1.v_id); |
---|
| 158 | |
---|
| 159 | while (1) { /* loop to read files from tape */ |
---|
| 160 | |
---|
| 161 | /* read in hdr1 label, error => all done */ |
---|
| 162 | if (read(tape,&hdr1,80) != 80) { |
---|
| 163 | exit(0); |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | if (superverbose) dump1(&hdr1); |
---|
| 167 | |
---|
| 168 | for (i=0,p=hdr1.h1_fname; i++<17 && *p!=' '; p++) |
---|
| 169 | if (*p>='A' && *p<='Z') *p |= 040; /* look for end */ |
---|
| 170 | *p = '\0'; /* terminate name with null */ |
---|
| 171 | |
---|
| 172 | /* reextract version number from tape*/ |
---|
| 173 | convert(4,hdr1.h1_genno,&genno); |
---|
| 174 | convert(2,hdr1.h1_gverno,&genver); |
---|
| 175 | version = (genno-1)*100 + genver + 1; |
---|
| 176 | |
---|
| 177 | if (vnos) sprintf(filename,"%s.%d",hdr1.h1_fname,version); |
---|
| 178 | else strcpy(filename,hdr1.h1_fname); |
---|
| 179 | |
---|
| 180 | /* see if file on list of files to be extracted */ |
---|
| 181 | match = 0; |
---|
| 182 | for(i = bf; i < ef; i++) |
---|
| 183 | if(strcmp(argv[i],filename) == 0) { |
---|
| 184 | match = 1; |
---|
| 185 | break; |
---|
| 186 | } |
---|
| 187 | |
---|
| 188 | if(bf >= ef) match = 1; |
---|
| 189 | if(list) match = 0; /* don't retrieve files if |
---|
| 190 | listing volume contents*/ |
---|
| 191 | first = 0; |
---|
| 192 | file = bitbucket; |
---|
| 193 | if(match) { |
---|
| 194 | if(verbose) printf("Creating file %s, ",filename) ; |
---|
| 195 | fflush(stdout); /* let him see it */ |
---|
| 196 | file = creat(filename,0666); /* and use remainder as name */ |
---|
| 197 | first = 1; |
---|
| 198 | if (file==-1) { |
---|
| 199 | printf("Can't create %s, skipping file on tape.\n" |
---|
| 200 | ,filename); |
---|
| 201 | file = bitbucket; |
---|
| 202 | } |
---|
| 203 | } |
---|
| 204 | if(list) { first = 1; printf("%s, ",filename) ; } |
---|
| 205 | |
---|
| 206 | if (read(tape,&hdr2,80) != 80) { |
---|
| 207 | printf("Bad HDR2 record!\n"); |
---|
| 208 | exit(1); |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | if (superverbose) dump2(&hdr2); |
---|
| 212 | convert(5,&hdr2.h2_bsize[0],&fbsize); |
---|
| 213 | |
---|
| 214 | |
---|
| 215 | ftype = BINARY; /*default to binary input*/ |
---|
| 216 | /* lets decode the record format and forms control properly*/ |
---|
| 217 | switch(hdr2.h2_format) { |
---|
| 218 | case 'D': |
---|
| 219 | switch(hdr2.h2_form) { |
---|
| 220 | case 'A': ftype = FORTRAN; |
---|
| 221 | break; |
---|
| 222 | case 'M': ftype = VARIABLE; |
---|
| 223 | break; |
---|
| 224 | case ' ': ftype = CRLF; |
---|
| 225 | break; |
---|
| 226 | default: fprintf(stderr, |
---|
| 227 | "ansi: bad forms, binary assumed in %s.\n" |
---|
| 228 | ,filename); |
---|
| 229 | ftype = BINARY; |
---|
| 230 | break; |
---|
| 231 | } |
---|
| 232 | break; |
---|
| 233 | case 'F': |
---|
| 234 | ftype = BINARY; |
---|
| 235 | if(hdr2.h2_form != 'M') |
---|
| 236 | fprintf(stderr, |
---|
| 237 | "ansi: unknown type, binary assumed in %s.\n", |
---|
| 238 | filename); |
---|
| 239 | break; |
---|
| 240 | default: |
---|
| 241 | ftype = BINARY; |
---|
| 242 | fprintf(stderr,"ansi: unknown format, binary assumed in %s.\n", |
---|
| 243 | filename); |
---|
| 244 | } |
---|
| 245 | if(fbinary) ftype = BINARY; |
---|
| 246 | |
---|
| 247 | if(first) { |
---|
| 248 | char *out; /*text string to output*/ |
---|
| 249 | printf("file type is ") ; |
---|
| 250 | switch(ftype) { |
---|
| 251 | case BINARY: out = "fixed binary or stream.";break; |
---|
| 252 | case CRLF: out = "text."; break; |
---|
| 253 | case FORTRAN: out = "fortran text."; break; |
---|
| 254 | case VARIABLE: out = "variable binary."; break; |
---|
| 255 | default: out = "unknown."; break; |
---|
| 256 | } |
---|
| 257 | printf("%s\n",out); |
---|
| 258 | } |
---|
| 259 | |
---|
| 260 | /* skip rest of header file, last read skips eof */ |
---|
| 261 | while ((c = read(tape,buffer,80)) == 80); |
---|
| 262 | |
---|
| 263 | /* binary files get read as is... */ |
---|
| 264 | if (ftype == BINARY) while (1) { |
---|
| 265 | c = read(tape,buffer,fbsize); |
---|
| 266 | if (c == 0) break; |
---|
| 267 | write(file,buffer,c); |
---|
| 268 | } |
---|
| 269 | else while (1) { /* read in records of file */ |
---|
| 270 | c = read(tape,buffer,fbsize);/*read in next record from tape */ |
---|
| 271 | if (c == 0) break; /* EOF => all done with this file */ |
---|
| 272 | if (c != fbsize) printf("Record wrong size (count = %d)\n",c); |
---|
| 273 | p = buffer; |
---|
| 274 | |
---|
| 275 | /* ^ as count means end of buffer */ |
---|
| 276 | while (p < &buffer[fbsize] && *p != '^') { |
---|
| 277 | int length; |
---|
| 278 | for (i=0,c=0; i<4; i++) c = c*10 + *p++ - '0'; |
---|
| 279 | c -= 4; |
---|
| 280 | length = c; |
---|
| 281 | switch(ftype) { |
---|
| 282 | case FORTRAN: |
---|
| 283 | switch(*p) { /* do fortran crock */ |
---|
| 284 | default: |
---|
| 285 | case ' ': |
---|
| 286 | write(file,nl,1); /* NL */ |
---|
| 287 | break; |
---|
| 288 | case '0': |
---|
| 289 | write(file,nl,1); /* NL */ |
---|
| 290 | write(file,nl,1); /* NL */ |
---|
| 291 | break; |
---|
| 292 | case '+': |
---|
| 293 | write(file,cr,1); /* CR */ |
---|
| 294 | break; |
---|
| 295 | case '1': |
---|
| 296 | write(file,ff,1); /* FF */ |
---|
| 297 | break; |
---|
| 298 | } |
---|
| 299 | write(file,p+1,c-1); |
---|
| 300 | break; |
---|
| 301 | case VARIABLE: |
---|
| 302 | write(file,&length,sizeof(length)); |
---|
| 303 | write(file,p,c); |
---|
| 304 | write(file,&length,sizeof(length)); |
---|
| 305 | break; |
---|
| 306 | case CRLF: |
---|
| 307 | write(file,p,c); |
---|
| 308 | write(file,nl,1); /*add newline*/ |
---|
| 309 | break; |
---|
| 310 | } |
---|
| 311 | p += c; |
---|
| 312 | } |
---|
| 313 | } /* end of record reading loop */ |
---|
| 314 | /* terminate last fortran record */ |
---|
| 315 | if(ftype == FORTRAN) write(file,nl,1); |
---|
| 316 | |
---|
| 317 | if (file != bitbucket) close(file); |
---|
| 318 | |
---|
| 319 | /* skip EOF file, last read skips eof */ |
---|
| 320 | while ((c = read(tape,buffer,80)) == 80); |
---|
| 321 | } /* end of loop to read files */ |
---|
| 322 | } |
---|
| 323 | |
---|
| 324 | dump1(h) |
---|
| 325 | struct header1 *h; |
---|
| 326 | { |
---|
| 327 | printf("label id %3.3s\n",h->h1_lid); |
---|
| 328 | printf("label number %c\n",h->h1_num); |
---|
| 329 | printf("name %17.17s\n",h->h1_fname); |
---|
| 330 | printf("set id %6.6s\n",h->h1_fset); |
---|
| 331 | printf("section number %4.4s\n",h->h1_fsec); |
---|
| 332 | printf("sequence number %4.4s\n",h->h1_seqno); |
---|
| 333 | printf("generation number %4.4s\n",h->h1_genno); |
---|
| 334 | printf("generation version number %2.2s\n",h->h1_gverno); |
---|
| 335 | printf("creation date %6.6s\n",h->h1_credate); |
---|
| 336 | printf("expiration date %6.6s\n",h->h1_exdate); |
---|
| 337 | printf("access code %c\n",h->h1_access); |
---|
| 338 | printf("block count %6.6s\n",h->h1_blcount); |
---|
| 339 | printf("system code %13.13s\n",h->h1_syscode); |
---|
| 340 | return; |
---|
| 341 | } |
---|
| 342 | dump2(h) |
---|
| 343 | struct header2 *h; |
---|
| 344 | { |
---|
| 345 | printf("label id %3.3s\n",h->h2_lid); |
---|
| 346 | printf("label number %c\n",h->h2_num); |
---|
| 347 | printf("format %c\n",h->h2_format); |
---|
| 348 | printf("block size %5.5s\n",h->h2_bsize); |
---|
| 349 | printf("record length %5.5s\n",h->h2_rlength); |
---|
| 350 | printf("rms flag %c\n",h->h2_flag); |
---|
| 351 | printf("forms control %c\n",h->h2_form); |
---|
| 352 | printf("buffer offset %2.2s\n",h->h2_buffoff); |
---|
| 353 | return; |
---|
| 354 | } |
---|
| 355 | |
---|
| 356 | convert(howmany,where,value) |
---|
| 357 | int howmany; /*number of characters in numeric field*/ |
---|
| 358 | char *where; /*where to get the characters*/ |
---|
| 359 | int *value; /*place to put the result*/ |
---|
| 360 | { |
---|
| 361 | int i; |
---|
| 362 | char *cptr = &cbuffer[0]; /*pointer to temp area*/ |
---|
| 363 | while(howmany--) *cptr++ = *where++; |
---|
| 364 | *cptr++ = '\0'; /*terminate the string*/ |
---|
| 365 | *value = atoi(cbuffer); /*get and store the value*/ |
---|
| 366 | } |
---|