Received: from seismo.css.gov by AMSAA.ARPA id a013221; 15 Oct 86 18:28 EDT Received: from ubc-vision.UUCP by seismo.CSS.GOV (5.54/1.14) id AA09297; Wed, 15 Oct 86 18:29:30 EDT Received: by ubc-vision.UUCP id AA09634; Wed, 15 Oct 86 12:50:40 pdt Received: by pembina.alberta.UUCP (4.12/3.14) id AA10116; Wed, 15 Oct 86 11:59:50 mdt Received: by myrias.UUCP (4.12/4.7) id AA10621; Wed, 15 Oct 86 11:46:15 mdt Date: Wed, 15 Oct 86 11:40:07 mdt From: ubc-vision!alberta!myrias!cg@seismo.CSS.GOV (Chris Gray) Message-Id: <8610151740.AA28641@myrias.UUCP> To: towson@amsaa.arpa Subject: UUDECODE.DRC #util.g /* * uudecode.drc * Decode an ASCII representation into a binary file. This is the * reverse of uuencode. The single parameter is the name of the * uuencoded file to decode. The input file contains the name to use * for the binary file created. It can contain more than one file, even * though uuencode can't directly produce such a beast. */ word BUFF_SIZE = 10000, /* nice and big */ MAX_BYTES = 45, /* maximum bytes per encoded line */ MAX_LINE = 100; /* maximum input line we use */ channel input text Chin; channel output binary Chout; file(BUFF_SIZE) InputFile, OutputFile; [MAX_LINE] char LineBuff; /* buffer for input line */ word LineMax, LinePos; /* count/position in input line */ bool Eof; /* * getLine - * Read an input line into LineBuff/LineMax. */ proc getLine()void: char ch; LineMax := 0; while read(Chin; ch) do if LineMax ~= MAX_LINE then LineBuff[LineMax] := ch; LineMax := LineMax + 1; fi; od; if ioerror(Chin) = CH_MISSING then readln(Chin;); else Eof := true; fi; LinePos := 0; corp; /* * getWord - * Peel an input word off of the input line. */ proc getWord()*char: *char p; p := &LineBuff[LinePos]; while LinePos < LineMax and LineBuff[LinePos] ~= ' ' do LinePos := LinePos + 1; od; LineBuff[LinePos] := '\e'; LinePos := LinePos + 1; p corp; /* * isWord - * Compare two words for equality. */ proc isWord(*char p, q)bool: while p* = q* and p* ~= '\e' do p := p + 1; q := q + 1; od; p* = q* corp; /* * decodeChar - * Decode a single character to a six bit value. */ proc decodeChar(char ch)byte: if ch >= ' ' + 1 and ch <= ' ' + ((1 << 6) - 1) then ch - ' ' elif ch = '`' then 0 else writeln("Bad encoded character: ", ch - '\e'); close(Chout); close(Chin); exit(1); 0 fi corp; /* * decodeFile - * Decode the file given already opened descriptors, etc. */ proc decodeFile()void: [MAX_BYTES] byte buff; word count, i, j; byte b1, b2, b3, b4; /* fetch and decode lines until we find one starting with "end" */ while getLine(); not isWord(getWord(), "end") do /* check for a valid length line */ if LineMax < 1 or LineMax > MAX_BYTES * 4 / 3 + 1 or (LineMax - 1) % 4 ~= 0 then writeln("Invalid line length: ", LineMax); close(Chout); close(Chin); exit(1); fi; /* get and check the actual count of encoded bytes on this line */ count := decodeChar(LineBuff[0]); if (LineMax - 1) / 4 ~= (count + 2) / 3 then writeln("Invalid record length: ", count, " : ", LineMax); close(Chout); close(Chin); exit(1); fi; /* decode the line - groups of 4 characters yield three bytes */ j := 0; i := 1; while i ~= LineMax do b1 := decodeChar(LineBuff[i + 0]); b2 := decodeChar(LineBuff[i + 1]); b3 := decodeChar(LineBuff[i + 2]); b4 := decodeChar(LineBuff[i + 3]); buff[j + 0] := b1 << 2 | b2 >> 4; buff[j + 1] := b2 << 4 | b3 >> 2; buff[j + 2] := b3 << 6 | b4; j := j + 3; i := i + 4; od; /* write out the correct number (1 - 45) of bytes */ i := 0; while i ~= count do write(Chout; buff[i]); i := i + 1; od; od; corp; /* * decode - * Decode all of the encoded files in the already opened input file. */ proc decode()void: *char outFileName; FILENAME fn; bool gotBegin, doneFile; doneFile := false; /* decode files until there are no more left */ while not Eof do gotBegin := false; /* skip lines until we find a 'begin' line or we hit end-of-file */ while not Eof and not gotBegin do getLine(); outFileName := getWord(); if isWord(outFileName, "begin") then outFileName := getWord(); while outFileName* >= '0' and outFileName* <= '7' do outFileName := outFileName + 1; od; if outFileName* = '\e' then outFileName := getWord(); if outFileName* ~= '\e' then gotBegin := true; fi; fi; fi; od; /* if we just found a 'begin' line, go decode an encoded file */ if gotBegin then writeln("Decoding file '", outFileName, "'"); /* open output file, etc. */ SetFileName(fn, outFileName); pretend(FileDestroy(fn), void); if not FileCreate(fn) then writeln("Can't create output file '", outFileName, "'"); close(Chin); exit(1); fi; if not open(Chout, OutputFile, outFileName) then writeln("Can't open output file '", outFileName, "'"); close(Chin); exit(1); fi; /* go decode the file */ decodeFile(); /* close file */ close(Chout); doneFile := true; fi; od; /* if we found no 'begin' line in the whole input file, then complain */ if not doneFile then writeln("No 'begin' line found."); close(Chin); exit(1); fi; corp; /* * main - * The main program. Get the command line parameters and open and decode * each one. Each input file is decoded into 1 or more output binary * files. */ proc main()void: *char par; par := GetPar(); if par = nil then writeln("usage: uudecode file1.typ ... filen.typ"); else while par ~= nil do /* try to open the specified input file */ if not open(Chin, InputFile, par) then writeln("Can't open input file '", par, "'"); exit(1); fi; /* initialize for reading the input line */ Eof := false; decode(); close(Chin); par := GetPar(); od; fi; corp;