[comp.lang.perl] uuencode in perl?

jh@efd.lth.se (Joergen Haegg) (02/06/91)

I was trying to write a uuencode/uudecode program in perl.
(Yes, I know, the c-version is free, but it's fun to try ;-)
Not very difficult, since pack has 'u'.
But I compared the output with Suns uuencode:

sub encode
{
        ($name, $file, @x) = @_;

        $st_mode = 0622;
        if ($file)
        {
                &Stat($file) || die "stat $file: $!";
        }
        printf OUT "begin %03o %s\n", $st_mode&0777, $file;

        open(IN, $file) || die "open $file: $!";

        while (($n = sysread(IN, $row, 45)) > 0)
        {
                $uline = pack("u", $row);
                print OUT "$uline";
        }
        close (IN);
        print OUT "\nend\n";
}

Testfile:
  PID TT STAT  TIME COMMAND
17364 p2 S     7:12 bash -login
17582 p2 TW    0:04 view ../route.c
18371 p2 R     0:00 ps
 2505 p4 I     2:31 -su (bash)
18369 p4 I     0:00 vi uued


This script gave 
begin 644 z
M("!0240@5%0@4U1!5" @5$E-12!#3TU-04Y$"C$W,S8T(' R(%,@(" @(#<Z
M,3(@8F%S:" M;&]G:6X*,3<U.#(@<#(@5%<@(" @,#HP-"!V:65W("XN+W)O
M=71E+F,*,3@S-S$@<#(@4B @(" @,#HP,"!P<PH@,C4P-2!P-"!)(" @(" R
K.C,Q("US=2 H8F%S:"D*,3@S-CD@<#0@22 @(" @,#HP,"!V:2!U=65D"@ R

end

Suns uuencode gave
begin 644 z
M("!0240@5%0@4U1!5" @5$E-12!#3TU-04Y$"C$W,S8T(' R(%,@(" @(#<Z
M,3(@8F%S:" M;&]G:6X*,3<U.#(@<#(@5%<@(" @,#HP-"!V:65W("XN+W)O
M=71E+F,*,3@S-S$@<#(@4B @(" @,#HP,"!P<PH@,C4P-2!P-"!)(" @(" R
K.C,Q("US=2 H8F%S:"D*,3@S-CD@<#0@22 @(" @,#HP,"!V:2!U=65D"B R

end

The last line differs in the end, '@ R' and 'B R'.
Uudecode says 'Short file' on my perl version.

And there seems to be two different formats of uuencode. A source
porgram I tried looked like this:
begin 644 z
M("!0240@5%0@4U1!5"`@5$E-12!#3TU-04Y$"C$W,S8T('`R(%,@("`@(#<Z
M,3(@8F%S:"`M;&]G:6X*,3<U.#(@<#(@5%<@("`@,#HP-"!V:65W("XN+W)O
M=71E+F,*,3@S-S$@<#(@4B`@("`@,#HP,"!P<PH@,C4P-2!P-"!)("`@("`R
K.C,Q("US=2`H8F%S:"D*,3@S-CD@<#0@22`@("`@,#HP,"!V:2!U=65D"B`R
`
end

Just like Sun's uuencode, but all spaces is backticks instead.

What is right and what is wrong?
-- 
Joergen Haegg				jh@efd.lth.se	postmaster@efd.lth.se
System manager @ efd			046-107492
Lund Institute of Technology		E-huset, DDG, Ole R|mers v. 3
					221 00 LUND, Sweden

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/09/91)

In article <1991Feb6.091933.27961@lth.se> jh@efd.lth.se (Joergen Haegg) writes:
: 
: I was trying to write a uuencode/uudecode program in perl.
: (Yes, I know, the c-version is free, but it's fun to try ;-)
: Not very difficult, since pack has 'u'.
: But I compared the output with Suns uuencode:
: 
: sub encode
: {
:         ($name, $file, @x) = @_;
: 
:         $st_mode = 0622;
:         if ($file)
:         {
:                 &Stat($file) || die "stat $file: $!";
:         }
:         printf OUT "begin %03o %s\n", $st_mode&0777, $file;
: 
:         open(IN, $file) || die "open $file: $!";
: 
:         while (($n = sysread(IN, $row, 45)) > 0)
:         {
:                 $uline = pack("u", $row);
:                 print OUT "$uline";
:         }
:         close (IN);
:         print OUT "\nend\n";
: }
: 
: Testfile:
:   PID TT STAT  TIME COMMAND
: 17364 p2 S     7:12 bash -login
: 17582 p2 TW    0:04 view ../route.c
: 18371 p2 R     0:00 ps
:  2505 p4 I     2:31 -su (bash)
: 18369 p4 I     0:00 vi uued
: 
: 
: This script gave 
: begin 644 z
: M("!0240@5%0@4U1!5" @5$E-12!#3TU-04Y$"C$W,S8T(' R(%,@(" @(#<Z
: M,3(@8F%S:" M;&]G:6X*,3<U.#(@<#(@5%<@(" @,#HP-"!V:65W("XN+W)O
: M=71E+F,*,3@S-S$@<#(@4B @(" @,#HP,"!P<PH@,C4P-2!P-"!)(" @(" R
: K.C,Q("US=2 H8F%S:"D*,3@S-CD@<#0@22 @(" @,#HP,"!V:2!U=65D"@ R
: 
: end
: 
: Suns uuencode gave
: begin 644 z
: M("!0240@5%0@4U1!5" @5$E-12!#3TU-04Y$"C$W,S8T(' R(%,@(" @(#<Z
: M,3(@8F%S:" M;&]G:6X*,3<U.#(@<#(@5%<@(" @,#HP-"!V:65W("XN+W)O
: M=71E+F,*,3@S-S$@<#(@4B @(" @,#HP,"!P<PH@,C4P-2!P-"!)(" @(" R
: K.C,Q("US=2 H8F%S:"D*,3@S-CD@<#0@22 @(" @,#HP,"!V:2!U=65D"B R
: 
: end
: 
: The last line differs in the end, '@ R' and 'B R'.
: Uudecode says 'Short file' on my perl version.

But the reason is not that.  (The reason is that the next line doesn't
have a space on it.)  That last line is 43 characters long, so the
last two characters are "don't care" characters.  uuencode is adding
two garbage characters that happen to be the same two characters that
were already there in its buffer from the end of the previous line.
Perl is using a null plus the last character from the previous line for
its garbage.  But the first character 'K' encodes a length of 43, so
uudecode will ignore them.

To fix your script, change that last print to:

    print OUT "`\nend\n";

I think what's going on is that uudecode goes until it sees a line with
a 0 length, rather than looking for "end" like a sane program.

: And there seems to be two different formats of uuencode. A source
: porgram I tried looked like this:
: begin 644 z
: M("!0240@5%0@4U1!5"`@5$E-12!#3TU-04Y$"C$W,S8T('`R(%,@("`@(#<Z
: M,3(@8F%S:"`M;&]G:6X*,3<U.#(@<#(@5%<@("`@,#HP-"!V:65W("XN+W)O
: M=71E+F,*,3@S-S$@<#(@4B`@("`@,#HP,"!P<PH@,C4P-2!P-"!)("`@("`R
: K.C,Q("US=2`H8F%S:"D*,3@S-CD@<#0@22`@("`@,#HP,"!V:2!U=65D"B`R
: `
: end
: 
: Just like Sun's uuencode, but all spaces is backticks instead.

This is a variant that tries to avoid trouble on those systems that
delete trailing spaces on a line.  It's a reasonable thing, so 4.0
will do it.

There's yet another format that adds a checksum character on the end,
but I haven't tried to figure that one out yet.  I suspect that the
unpack checksummer could handle it easily enough.

: What is right and what is wrong?

They're both right.  By the time you do (ch - ' ') & 077, space and ` are
equivalent.

Larry