1 | /* |
---|
2 | * $Source: /afs/dev.mit.edu/source/repository/athena/bin/ansi/ansi.c,v $ |
---|
3 | * $Author: ghudson $ |
---|
4 | * $Locker: $ |
---|
5 | * $Header: /afs/dev.mit.edu/source/repository/athena/bin/ansi/ansi.c,v 1.2 1997-10-02 17:27:42 ghudson 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.2 1997-10-02 17:27:42 ghudson 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 | } |
---|