kuo@skatter.UUCP (Dr. Peter Kuo) (07/27/87)
I just dug up my copies of the (much demanded) UUenc/decode sources from a backup diskette. Here we go. Maybe Brandon Allbery would like to put this with <comp.sources.misc> for his monthly distribution with PK{X}ARC? I just thought this is a better newsgroup for this posting (no offense Brandon; and *no* flames please). The sources are packed into a shar file. There are both C and Turbo Pascal sources, as well as one for VMS. Enjoy. ... Peter/ ------------------------------------------------------------------------------- Peter Kuo | Bitnet (VMS) : KUO@SASK Accelerator Laboratory | (a.k.a. The Beam Warehouse) | uucp (Unix) : !alberta\ Univ. of Saskatchewan | !ihnp4 -- !sask!skatter!kuo Saskatoon, Saskatchewan | !utcsri / CANADA S7N 0W0 | (Earth) | Ma Bell : (306) 966-6059 Disclaimer: I don't know what I am saying, I'm only a physicist. Don't quote me on anything! I speak only for myself. =========== Note: 1) UUDECODE.PAS/UUENCODE.PAS are slightly different from the "standard" Unix uude/encode. This set of routines translate the blank into a ` (and back) so that some MAILERS do not truncate the line if the last character in the UUENCODED file is a blank. This is a known problem in sending files from APRAnet to Bitnet, for example. I usually use the Unix uuencode, pass the output thru a home-brew filter which adds an extra character to the end of each line (uudecode stops scanning at byte 63) so the lines will not get truncated. 2) VMSDECOD.PAS is for VAX/VMS. Disclaimer: I did not write any of these programs but have used them and they seem to work. I got most of these routines off SIMTEL20 before it got shut down from e-mail access. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # uudecode.c # uuencode.c # uude.pas # uudecode.pas # uuen.pas # uuencode.pas # vmsdecod.pas # This archive created: Sun Jul 26 16:07:43 1987 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'uudecode.c' then echo shar: "will not over-write existing file 'uudecode.c'" else cat << \SHAR_EOF > 'uudecode.c' /* * uudecode [input] * * if input not specified, get input from stdin * * Create the specified file, decoding as you go. * Used with uuencode. * * Modified for use with Microsoft C and VAX/VMS. * Define CI86 symbol to use with CI86. */ #ifndef VMS #include <stdio.h> #ifndef MSDOS #include <pwd.h> #endif /* ifndef MSDOS */ #ifndef CI86 #include <sys/types.h> #include <sys/stat.h> #endif #else /* ifndef VMS */ #include stdio #include types #include stat #endif /* ifndef VMS */ /* single character decode */ #define DEC(c) (((c) - ' ') & 077) main(argc, argv) char **argv; { FILE *in, *out; #ifndef CI86 struct stat sbuf; #endif int mode; char dest[128]; char buf[80]; /* optional input arg */ if (argc > 1) { if ((in = fopen(argv[1], "r")) == NULL) { perror(argv[1]); exit(1); } argv++; argc--; } else in = stdin; if (argc != 1) { fprintf(stderr, "Usage: uudecode [infile]\n"); exit(2); } /* search for header line */ for (;;) { if (fgets(buf, sizeof buf, in) == NULL) { fprintf(stderr, "No begin line\n"); exit(3); } if (strncmp(buf, "begin ", 6) == 0) break; } sscanf(buf, "begin %o %s", &mode, dest); /* handle ~user/file format */ #ifndef MSDOS #ifndef VMS if (dest[0] == '~') { char *sl; struct passwd *getpwnam(); char *index(); struct passwd *user; char dnbuf[100]; sl = index(dest, '/'); if (sl == NULL) { fprintf(stderr, "Illegal ~user\n"); exit(3); } *sl++ = 0; user = getpwnam(dest+1); if (user == NULL) { fprintf(stderr, "No such user as %s\n", dest); exit(4); } strcpy(dnbuf, user->pw_dir); strcat(dnbuf, "/"); strcat(dnbuf, sl); strcpy(dest, dnbuf); } #endif /* ifndef VMS */ #endif /* ifndef MSDOS */ /* create output file */ #ifdef MSDOS /* binary output file */ out = fopen(dest, "wb"); #else #ifdef VMS out = fopen(dest, "w", "rfm=var"); #else out = fopen(dest, "w"); #endif /* ifdef VMS */ #endif /* ifdef MSDOS */ if (out == NULL) { perror(dest); exit(4); } #ifndef CI86 chmod(dest, mode); #endif decode(in, out); if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { fprintf(stderr, "No end line\n"); exit(5); } #ifndef VMS exit(0); #else exit(1); /* VMS successful */ #endif } /* * copy from in to out, decoding as you go along. */ decode(in, out) FILE *in; FILE *out; { char buf[80]; char *bp; int n; for (;;) { /* for each input line */ if (fgets(buf, sizeof buf, in) == NULL) { fprintf(stderr, "Short file\n"); exit(10); } n = DEC(buf[0]); if (n <= 0) break; bp = &buf[1]; while (n > 0) { outdec(bp, out, n); bp += 4; n -= 3; } } } /* * output a group of 3 bytes (4 input characters). * the input chars are pointed to by p, they are to * be output to file f. n is used to tell us not to * output all of them at the end of the file. */ outdec(p, f, n) char *p; FILE *f; { int c1, c2, c3; c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; c3 = DEC(p[2]) << 6 | DEC(p[3]); if (n >= 1) putc(c1, f); if (n >= 2) putc(c2, f); if (n >= 3) putc(c3, f); } /* fr: like read but stdio */ int fr(fd, buf, cnt) FILE *fd; char *buf; int cnt; { int c, i; for (i=0; i<cnt; i++) { c = getc(fd); if (c == EOF) return(i); buf[i] = c; } return (cnt); } /* * Return the ptr in sp at which the character c appears; * NULL if not found */ #define NULL 0 char * index(sp, c) register char *sp, c; { do { if (*sp == c) return(sp); } while (*sp++); return(NULL); } SHAR_EOF fi if test -f 'uuencode.c' then echo shar: "will not over-write existing file 'uuencode.c'" else cat << \SHAR_EOF > 'uuencode.c' /* * uuencode [input [output] ] * * if output not specified, output to stdout * if input not specified, input from stdin * * Encode a file so it can be mailed to a remote system. * * Modified for use with Microsoft C and VAX/VMS. * Define CI86 symbol to use with CI86. */ #ifndef VMS #include <stdio.h> #ifndef CI86 #include <sys/types.h> #include <sys/stat.h> #endif #else /* ifndef VMS */ #include stdio #include types #include stat #endif /* ifndef VMS */ /* ENC is the basic 1 character encoding function to make a char printing */ #define ENC(c) (((c) & 077) + ' ') main(argc, argv) char **argv; { FILE *in, *out; #ifndef CI86 struct stat sbuf; #endif int mode; /* if 3 arguments, then output file specified */ if (argc > 2) { if ((out = fopen(argv[2], "w")) == NULL) { perror(argv[2]); exit(3); } argc--; } else out = stdout; if (argc > 1) { #ifdef MSDOS /* Use binary mode */ if ((in = fopen(argv[1], "rb")) == NULL) { #else if ((in = fopen(argv[1], "r")) == NULL) { #endif perror(argv[1]); exit(1); } argc--; } else in = stdin; if (argc != 1) { fprintf(stderr,"Usage: uuencode [infile [outfile] ]\n"); exit(2); } #ifndef CI86 /* figure out the input file mode */ fstat(fileno(in), &sbuf); mode = sbuf.st_mode & 0777; #else mode = 0; /* default to normal mode */ #endif fprintf(out,"begin %o %s\n", mode, argv[1]); encode(in, out); fprintf(out,"end\n"); #ifndef VMS exit(0); #else exit(1); /* VMS successful */ #endif } /* * copy from in to out, encoding as you go along. */ encode(in, out) FILE *in; FILE *out; { char buf[80]; int i, n; for (;;) { /* 1 (up to) 45 character line */ n = fr(in, buf, 45); putc(ENC(n), out); for (i=0; i<n; i += 3) outdec(&buf[i], out); putc('\n', out); if (n <= 0) break; } } /* * output one group of 3 bytes, pointed at by p, on file f. */ outdec(p, f) char *p; FILE *f; { int c1, c2, c3, c4; c1 = *p >> 2; c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03; c4 = p[2] & 077; putc(ENC(c1), f); putc(ENC(c2), f); putc(ENC(c3), f); putc(ENC(c4), f); } /* fr: like read but stdio */ int fr(fd, buf, cnt) FILE *fd; char *buf; int cnt; { int c, i; for (i=0; i<cnt; i++) { c = getc(fd); if (c == EOF) return(i); buf[i] = c; } return (cnt); } SHAR_EOF fi if test -f 'uude.pas' then echo shar: "will not over-write existing file 'uude.pas'" else cat << \SHAR_EOF > 'uude.pas' program uudecode; CONST defaultSuffix = '.uue'; offset = 32; TYPE string80 = string[80]; VAR infile: text; outfile: file of byte; lineNum: integer; line: string80; procedure Abort(message: string80); begin {abort} writeln; if lineNum > 0 then write('Line ', lineNum, ': '); writeln(message); halt end; {Abort} procedure NextLine(var s: string80); begin {NextLine} LineNum := succ(LineNum); gotoxy(12,12); clreol; if lineNum > 1 then write('LineCount: ', lineNum - 1); readln(infile, s) end; {NextLine} procedure Init; procedure GetInFile; VAR infilename: string80; begin {GetInFile} if ParamCount = 0 then abort ('Usage: uudecode <filename>'); infilename := ParamStr(1); if pos('.', infilename) = 0 then infilename := concat(infilename, defaultSuffix); assign(infile, infilename); {$i-} reset(infile); {$i+} if IOresult > 0 then abort (concat('Can''t open ', infilename)); gotoxy(1,1); writeln ('Decoding ', infilename) end; {GetInFile} procedure GetOutFile; var header, mode, outfilename: string80; ch: char; procedure ParseHeader; VAR index: integer; Procedure NextWord(var word:string80; var index: integer); begin {nextword} word := ''; while header[index] = ' ' do begin index := succ(index); if index > length(header) then abort ('Incomplete header') end; while header[index] <> ' ' do begin word := concat(word, header[index]); index := succ(index) end end; {NextWord} begin {ParseHeader} header := concat(header, ' '); index := 7; NextWord(mode, index); NextWord(outfilename, index) end; {ParseHeader} begin {GetOutFile} if eof(infile) then abort('Nothing to decode.'); NextLine (header); while not ((copy(header, 1, 6) = 'begin ') or eof(infile)) do NextLine(header); writeln; if eof(infile) then abort('Nothing to decode.'); ParseHeader; assign(outfile, outfilename); gotoxy(1,2); writeln ('Destination is ', outfilename); {$i-} reset(outfile); {$i+} if IOresult = 0 then begin gotoxy(1,3); write ('Overwrite current ', outfilename, '? [Y/N] '); repeat read (kbd, ch); ch := UpCase(ch) until ch in ['Y', 'N']; writeln(ch); if ch = 'N' then abort ('Overwrite cancelled.') end; rewrite (outfile); end; {GetOutFile} begin {init} lineNum := 0; clrscr; writeln; writeln; GetInFile; GetOutFile; end; { init} Function CheckLine: boolean; begin {CheckLine} if line = '' then abort ('Blank line in file'); CheckLine := not (line[1] in [' ', '`']) end; {CheckLine} procedure DecodeLine; VAR lineIndex, byteNum, count, i: integer; chars: array [0..3] of byte; hunk: array [0..2] of byte; function nextch: char; begin {nextch} lineIndex := succ(lineIndex); if lineIndex > length(line) then abort('Line too short.'); if not (line[lineindex] in [' '..'`']) then abort('Illegal character in line.'); if line[lineindex] = '`' then nextch := ' ' else nextch := line[lineIndex] end; {nextch} procedure DecodeByte; procedure GetNextHunk; VAR i: integer; begin {GetNextHunk} for i := 0 to 3 do chars[i] := ord(nextch) - offset; hunk[0] := (chars[0] shl 2) + (chars[1] shr 4); hunk[1] := (chars[1] shl 4) + (chars[2] shr 2); hunk[2] := (chars[2] shl 6) + chars[3]; byteNum := 0 {; debug } end; {GetNextHunk} begin {DecodeByte} if byteNum = 3 then GetNextHunk; write (outfile, hunk[byteNum]); {writeln(bytenum, ' ', hunk[byteNum]);} byteNum := succ(byteNum) end; {DecodeByte} begin {DecodeLine} lineIndex := 0; byteNum := 3; count := (ord(nextch) - offset); for i := 1 to count do DecodeByte end; {DecodeLine} procedure terminate; var trailer: string80; begin {terminate} if eof(infile) then abort ('Abnormal end.'); NextLine (trailer); if length (trailer) < 3 then abort ('Abnormal end.'); if copy (trailer, 1, 3) <> 'end' then abort ('Abnormal end.'); close (infile); close (outfile); gotoxy(1,22); end; begin {uudecode} init; NextLine(line); while CheckLine do begin DecodeLine; NextLine(line) end; terminate end. SHAR_EOF fi if test -f 'uudecode.pas' then echo shar: "will not over-write existing file 'uudecode.pas'" else cat << \SHAR_EOF > 'uudecode.pas' program uudecode; CONST defaultSuffix = '.uue'; offset = 32; TYPE string80 = string[80]; VAR infile: text; fi : file of byte; outfile: file of byte; lineNum: integer; line: string80; size,remaining :real; procedure Abort(message: string80); begin {abort} writeln; if lineNum > 0 then write('Line ', lineNum, ': '); writeln(message); halt end; {Abort} procedure NextLine(var s: string80); begin {NextLine} LineNum := succ(LineNum); {write('.');} readln(infile, s); remaining:=remaining-length(s)-2; {-2 is for CR/LF} write('bytes remaining: ',remaining:7:0,' (', remaining/size*100.0:3:0,'%)',chr(13)); end; {NextLine} procedure Init; procedure GetInFile; VAR infilename: string80; begin {GetInFile} if ParamCount = 0 then abort ('Usage: uudecode <filename>'); infilename := ParamStr(1); if pos('.', infilename) = 0 then infilename := concat(infilename, defaultSuffix); assign(infile, infilename); {$i-} reset(infile); {$i+} if IOresult > 0 then abort (concat('Can''t open ', infilename)); writeln ('Decoding ', infilename); assign(fi,infilename); reset(fi); size:=FileSize(fi); close(fi); if size < 0 then size:=size+65536.0; remaining:=size; end; {GetInFile} procedure GetOutFile; var header, mode, outfilename: string80; ch: char; procedure ParseHeader; VAR index: integer; Procedure NextWord(var word:string80; var index: integer); begin {nextword} word := ''; while header[index] = ' ' do begin index := succ(index); if index > length(header) then abort ('Incomplete header') end; while header[index] <> ' ' do begin word := concat(word, header[index]); index := succ(index) end end; {NextWord} begin {ParseHeader} header := concat(header, ' '); index := 7; NextWord(mode, index); NextWord(outfilename, index) end; {ParseHeader} begin {GetOutFile} if eof(infile) then abort('Nothing to decode.'); NextLine (header); while not ((copy(header, 1, 6) = 'begin ') or eof(infile)) do NextLine(header); writeln; if eof(infile) then abort('Nothing to decode.'); ParseHeader; assign(outfile, outfilename); writeln ('Destination is ', outfilename); {$i-} reset(outfile); {$i+} if IOresult = 0 then begin write ('Overwrite current ', outfilename, '? [Y/N] '); repeat read (kbd, ch); ch := UpCase(ch) until ch in ['Y', 'N']; writeln(ch); if ch = 'N' then abort ('Overwrite cancelled.') end; rewrite (outfile); end; {GetOutFile} begin {init} lineNum := 0; GetInFile; GetOutFile; end; { init} Function CheckLine: boolean; begin {CheckLine} if line = '' then abort ('Blank line in file'); CheckLine := not (line[1] in [' ', '`']) end; {CheckLine} procedure DecodeLine; VAR lineIndex, byteNum, count, i: integer; chars: array [0..3] of byte; hunk: array [0..2] of byte; { procedure debug; var i: integer; procedure writebin(x: byte); var i: integer; begin for i := 1 to 8 do begin write ((x and $80) shr 7); x := x shl 1 end; write (' ') end; begin writeln; for i := 0 to 3 do writebin(chars[i]); writeln; for i := 0 to 2 do writebin(hunk[i]); writeln end; } function nextch: char; begin {nextch} lineIndex := succ(lineIndex); if lineIndex > length(line) then abort('Line too short.'); if not (line[lineindex] in [' '..'`']) then abort('Illegal character in line.'); { write(line[lineindex]:2);} if line[lineindex] = '`' then nextch := ' ' else nextch := line[lineIndex] end; {nextch} procedure DecodeByte; procedure GetNextHunk; VAR i: integer; begin {GetNextHunk} for i := 0 to 3 do chars[i] := ord(nextch) - offset; hunk[0] := (chars[0] shl 2) + (chars[1] shr 4); hunk[1] := (chars[1] shl 4) + (chars[2] shr 2); hunk[2] := (chars[2] shl 6) + chars[3]; byteNum := 0 {; debug } end; {GetNextHunk} begin {DecodeByte} if byteNum = 3 then GetNextHunk; write (outfile, hunk[byteNum]); {writeln(bytenum, ' ', hunk[byteNum]);} byteNum := succ(byteNum) end; {DecodeByte} begin {DecodeLine} lineIndex := 0; byteNum := 3; count := (ord(nextch) - offset); for i := 1 to count do DecodeByte end; {DecodeLine} procedure terminate; var trailer: string80; begin {terminate} if eof(infile) then abort ('Abnormal end.'); NextLine (trailer); if length (trailer) < 3 then abort ('Abnormal end.'); if copy (trailer, 1, 3) <> 'end' then abort ('Abnormal end.'); close (infile); close (outfile) end; begin {uudecode} init; NextLine(line); while CheckLine do begin DecodeLine; NextLine(line) end; terminate end. SHAR_EOF fi if test -f 'uuen.pas' then echo shar: "will not over-write existing file 'uuen.pas'" else cat << \SHAR_EOF > 'uuen.pas' Program uuencode; CONST header = 'begin'; trailer = 'end'; defaultMode = '644'; defaultExtension = '.uue'; offset = 32; charsPerLine = 60; bytesPerHunk = 3; sixBitMask = $3F; TYPE string80 = string[80]; VAR infile: file of byte; outfile: text; infilename, outfilename, mode: string80; lineNum, lineLength, numbytes, bytesInLine: integer; line: array [0..59] of char; hunk: array [0..2] of byte; chars: array [0..3] of byte; procedure Abort (message: string80); begin {abort} writeln(message); close(infile); close(outfile); halt end; {abort} procedure Init; procedure GetFiles; VAR i: integer; temp: string80; ch: char; begin {GetFiles} if ParamCount < 1 then abort ('No input file specified.'); infilename := ParamStr(1); {$I-} assign (infile, infilename); reset (infile); {$i+} if IOResult > 0 then abort (concat ('Can''t open file ', infilename)); write('Uuencoding file ', infilename); i := pos('.', infilename); if i = 0 then outfilename := infilename else outfilename := copy (infilename, 1, pred(i)); mode := defaultMode; if ParamCount > 1 then for i := 2 to ParamCount do begin temp := Paramstr(i); if temp[1] in ['0'..'9'] then mode := temp else outfilename := temp end; if pos ('.', outfilename) = 0 then outfilename := concat(outfilename, defaultExtension); assign (outfile, outfilename); writeln (' to file ', outfilename, '.'); {$i-} reset(outfile); {$i+} if IOresult = 0 then begin Write ('Overwrite current ', outfilename, '? [Y/N] '); repeat read (kbd, ch); ch := Upcase(ch) until ch in ['Y', 'N']; writeln (ch); if ch = 'N' then abort(concat (outfilename, ' not overwritten.')) end; close(outfile); {$i-} rewrite(outfile); {$i+} if ioresult > 0 then abort(concat('Can''t open ', outfilename)); end; {getfiles} begin {Init} clrscr; writeln; writeln; GetFiles; bytesInLine := 0; lineLength := 0; numbytes := 0; writeln; writeln (outfile, header, ' ', mode, ' ', infilename); linenum := 0; end; {init} procedure FlushLine; VAR i: integer; procedure writeout(ch: char); begin {writeout} if ch = ' ' then write(outfile, '`') else write(outfile, ch) end; {writeout} begin {FlushLine} gotoxy(12,12); clreol; linenum := linenum + 1; write('LineCount: ',linenum); writeout(chr(bytesInLine + offset)); for i := 0 to pred(lineLength) do writeout(line[i]); writeln (outfile); lineLength := 0; bytesInLine := 0 end; {FlushLine} procedure FlushHunk; VAR i: integer; begin {FlushHunk} if lineLength = charsPerLine then FlushLine; chars[0] := hunk[0] shr 2; chars[1] := (hunk[0] shl 4) + (hunk[1] shr 4); chars[2] := (hunk[1] shl 2) + (hunk[2] shr 6); chars[3] := hunk[2] and sixBitMask; for i := 0 to 3 do begin line[lineLength] := chr((chars[i] and sixBitMask) + offset); {write(line[linelength]:2);} lineLength := succ(lineLength) end; {writeln;} bytesInLine := bytesInLine + numbytes; numbytes := 0 end; {FlushHunk} procedure encode1; begin {encode1}; if numbytes = bytesperhunk then flushhunk; read (infile, hunk[numbytes]); numbytes := succ(numbytes) end; {encode1} procedure terminate; begin {terminate} if numbytes > 0 then flushhunk; if lineLength > 0 then begin flushLine; flushLine; end else flushline; writeln (outfile, trailer); close (outfile); close (infile); gotoxy(1,22); end; {terminate} begin {uuencode} init; while not eof (infile) do encode1; terminate end. {uuencode} SHAR_EOF fi if test -f 'uuencode.pas' then echo shar: "will not over-write existing file 'uuencode.pas'" else cat << \SHAR_EOF > 'uuencode.pas' Program uuencode; CONST header = 'begin'; trailer = 'end'; defaultMode = '644'; defaultExtension = '.uue'; offset = 32; charsPerLine = 60; bytesPerHunk = 3; sixBitMask = $3F; TYPE string80 = string[80]; VAR infile: file of byte; outfile: text; infilename, outfilename, mode: string80; lineLength, numbytes, bytesInLine: integer; line: array [0..59] of char; hunk: array [0..2] of byte; chars: array [0..3] of byte; size,remaining :real; { procedure debug; var i: integer; procedure writebin(x: byte); var i: integer; begin for i := 1 to 8 do begin write ((x and $80) shr 7); x := x shl 1 end; write (' ') end; begin for i := 0 to 2 do writebin(hunk[i]); writeln; for i := 0 to 3 do writebin(chars[i]); writeln; for i := 0 to 3 do writebin(chars[i] and sixBitMask); writeln end; } procedure Abort (message: string80); begin {abort} writeln(message); close(infile); close(outfile); halt end; {abort} procedure Init; procedure GetFiles; VAR i: integer; temp: string80; ch: char; begin {GetFiles} if ParamCount < 1 then abort ('No input file specified.'); infilename := ParamStr(1); {$I-} assign (infile, infilename); reset (infile); {$i+} if IOResult > 0 then abort (concat ('Can''t open file ', infilename)); size:=FileSize(infile); if size < 0 then size:=size+65536.0; remaining:=size; write('Uuencoding file ', infilename); i := pos('.', infilename); if i = 0 then outfilename := infilename else outfilename := copy (infilename, 1, pred(i)); mode := defaultMode; if ParamCount > 1 then for i := 2 to ParamCount do begin temp := Paramstr(i); if temp[1] in ['0'..'9'] then mode := temp else outfilename := temp end; if pos ('.', outfilename) = 0 then outfilename := concat(outfilename, defaultExtension); assign (outfile, outfilename); writeln (' to file ', outfilename, '.'); {$i-} reset(outfile); {$i+} if IOresult = 0 then begin Write ('Overwrite current ', outfilename, '? [Y/N] '); repeat read (kbd, ch); ch := Upcase(ch) until ch in ['Y', 'N']; writeln (ch); if ch = 'N' then abort(concat (outfilename, ' not overwritten.')) end; close(outfile); {$i-} rewrite(outfile); {$i+} if ioresult > 0 then abort(concat('Can''t open ', outfilename)); end; {getfiles} begin {Init} GetFiles; bytesInLine := 0; lineLength := 0; numbytes := 0; writeln (outfile, header, ' ', mode, ' ', infilename); end; {init} procedure FlushLine; VAR i: integer; procedure writeout(ch: char); begin {writeout} if ch = ' ' then write(outfile, '`') else write(outfile, ch) end; {writeout} begin {FlushLine} {write ('.');} write('bytes remaining: ',remaining:7:0,' (', remaining/size*100.0:3:0,'%)',chr(13)); writeout(chr(bytesInLine + offset)); for i := 0 to pred(lineLength) do writeout(line[i]); writeln (outfile); lineLength := 0; bytesInLine := 0 end; {FlushLine} procedure FlushHunk; VAR i: integer; begin {FlushHunk} if lineLength = charsPerLine then FlushLine; chars[0] := hunk[0] shr 2; chars[1] := (hunk[0] shl 4) + (hunk[1] shr 4); chars[2] := (hunk[1] shl 2) + (hunk[2] shr 6); chars[3] := hunk[2] and sixBitMask; {debug;} for i := 0 to 3 do begin line[lineLength] := chr((chars[i] and sixBitMask) + offset); {write(line[linelength]:2);} lineLength := succ(lineLength) end; {writeln;} bytesInLine := bytesInLine + numbytes; numbytes := 0 end; {FlushHunk} procedure encode1; begin {encode1}; if numbytes = bytesperhunk then flushhunk; read (infile, hunk[numbytes]); remaining:=remaining-1; numbytes := succ(numbytes) end; {encode1} procedure terminate; begin {terminate} if numbytes > 0 then flushhunk; if lineLength > 0 then begin flushLine; flushLine; end else flushline; writeln (outfile, trailer); close (outfile); close (infile); end; {terminate} begin {uuencode} init; while not eof (infile) do encode1; terminate; writeln; end. {uuencode} SHAR_EOF fi if test -f 'vmsdecod.pas' then echo shar: "will not over-write existing file 'vmsdecod.pas'" else cat << \SHAR_EOF > 'vmsdecod.pas' program uudecode_vms (INPUT,OUTPUT,INFILE,OUTFILE); { Original source pilfered from the MS-DOS turbo version on SIMTEL20} { Converted from Turbo to Vax-Pascal by Erik Olson, Harvey Mudd College (EOLSON@HMCVAX.BITNET) (eolson@muddcs.UUCP) 10/86 } {Corrected small bug for End of file - 10/15/86 eol} CONST offset = 32; TYPE string80 = varying[80] of char; pack_128 = packed array[1..128] of char; VAR infile: text; outfile: file of pack_128; lineNum: integer; line: string80; outidx : integer; outbuf : pack_128; Procedure Writebin(ch : char); begin if outidx = 128 then begin write(outfile,outbuf); outidx := 1; end else outidx := outidx + 1; outbuf[outidx] := ch; end; procedure Abort(message: string80); begin {abort} writeln; if lineNum > 0 then write('Line ', lineNum, ': '); writeln(message); end; {Abort} procedure NextLine(var s: string80); begin {NextLine} LineNum := succ(LineNum); if linenum mod 50 = 1 then writeln(LineNum); readln(infile, s) end; {NextLine} procedure Init; procedure GetInFile; VAR infilename: string80; begin {GetInFile} write('_File: '); readln(infilename); open(infile,infilename,history := old); reset(infile); writeln ('Decoding '+infilename) end; {GetInFile} procedure GetOutFile; var header, mode, outfilename: string80; ch: char; procedure ParseHeader; VAR index: integer; Procedure NextWord(var word:string80; var index: integer); begin {nextword} word := ''; while header[index] = ' ' do begin index := succ(index); if index > length(header) then abort ('Incomplete header') end; while header[index] <> ' ' do begin word := word+header[index]; index := succ(index) end end; {NextWord} begin {ParseHeader} header := header+' '; index := 7; NextWord(mode, index); NextWord(outfilename, index) end; {ParseHeader} begin {GetOutFile} if eof(infile) then abort('Nothing to decode.'); NextLine (header); while not ((substr(header,1,6) = 'begin ') or eof(infile)) do NextLine(header); writeln; if eof(infile) then abort('Nothing to decode.'); ParseHeader; open(outfile, outfilename,history := new); writeln ('Destination is ', outfilename); rewrite (outfile); end; {GetOutFile} begin {init} lineNum := 0; GetInFile; GetOutFile; end; { init} Function CheckLine: boolean; begin {CheckLine} if line = '' then abort ('Blank line in file'); CheckLine := not (line[1] in [' ', '`']) end; {CheckLine} procedure DecodeLine; VAR lineIndex, byteNum, count, i: integer; chars: array [0..3] of integer; hunk: array [0..2] of integer; function nextch: char; begin {nextch} lineIndex := succ(lineIndex); if lineIndex > length(line) then abort('Line too short.'); if not (line[lineindex] in [' '..'`']) then abort('Illegal character in line.'); if line[lineindex] = '`' then nextch := ' ' else nextch := line[lineIndex] end; {nextch} procedure DecodeByte; procedure GetNextHunk; VAR i: integer; begin {GetNextHunk} for i := 0 to 3 do chars[i] := ord(nextch) - offset; hunk[0] := (chars[0] * 4) + (chars[1] div 16); hunk[1] := (chars[1] * 16) + (chars[2] div 4); hunk[2] := (chars[2] * 64) + chars[3]; byteNum := 0 end; {GetNextHunk} begin {DecodeByte} if byteNum = 3 then GetNextHunk; writebin (chr(hunk[byteNum])); byteNum := succ(byteNum) end; {DecodeByte} begin {DecodeLine} lineIndex := 0; byteNum := 3; count := (ord(nextch) - offset); for i := 1 to count do DecodeByte end; {DecodeLine} procedure terminate; var trailer: string80; begin {terminate} if eof(infile) then abort ('Abnormal end.'); NextLine (trailer); if length (trailer) < 3 then abort ('Abnormal end.'); if substr (trailer, 1, 3) <> 'end' then abort ('Abnormal end.'); write(outfile,outbuf); close (infile); close (outfile) end; begin {uudecode} init; NextLine(line); while CheckLine do begin DecodeLine; NextLine(line) end; terminate end. SHAR_EOF fi exit 0 # End of shell archive