3

This question is a followup on this question, as I figured out the solution I presented in the previous question does not work anymore. It worked sometime, but now expect does not work as expected. Here is the full code again:

#!/bin/bash
MYPWD="mypassword"

expect -c ' 
    spawn zipcloak test.upd
    expect "*Enter password*" 
    sleep 1
    send  "'"$MYPWD"'\r"
    sleep 1
    expect "*Verify password*" 
    sleep 1
    send  "'"$MYPWD"'\r"
    sleep 1
    '

This bash script does not encrypt the file test.upd, but creates files in my directory starting with "zi", like zi0gA1rU or zi8Vv6OD.

Why is that? What are those files? Why does the above script sometimes work, and sometimes it does not? Is there no way to make expect to behave as it should?

Where can I find the source code of zipcloak, so I can rewrite it to avoid using expect?

Additional information:

  • I have to execute this command as root, as the zipfile has root rights. Maybe that is important?

    zipcloak -v Copyright (c) 1990-2008 Info-ZIP - Type 'zipcloak "-L"' for software license.

    This is ZipCloak 3.0 (July 5th 2008), by Info-ZIP. Currently maintained by E. Gordon. Please send bug reports to the authors using the web page at www.info-zip.org; see README for details.

    Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip, as of above date; see http://www.info-zip.org/ for other sites.

    Compiled with gcc 4.6.1 for Unix (Linux ELF) on Jun 11 2011.

    ZipCloak special compilation options: [encryption, version 2.91 of 05 Jan 2007]

After it stopped working, I needed to set the last sleep to 2. Then it worked again. But later, this also did not work anymore. So I set the sleep to 5 seconds. For now, my script is working. But NOT reliable.

Debug output with exp_internal 1 set:

spawn /usr/bin/test.upd
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {28746}

expect: does "" (spawn_id exp6) match glob pattern "*Enter password*"? no
Enter password: 
expect: does "Enter password: " (spawn_id exp6) match glob pattern "*Enter password*"? yes
expect: set expect_out(0,string) "Enter password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "Enter password: "
send: sending "XXX\r" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "*Verify password*"? no

Verify password: 
expect: does "\r\nVerify password: " (spawn_id exp6) match glob pattern "*Verify password*"? yes
expect: set expect_out(0,string) "\r\nVerify password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\r\nVerify password: "
send: sending "XXX\r" to { exp6 }
argv[0] = expect  argv[1] = -c  argv[2] = 
    exp_internal 1
    spawn /usr/bin/zipcloak "test.upd"
    expect "*Enter password*"
    sleep 1
    send  "XXX\r"
    sleep 1
    expect "*Verify password*"
    sleep 1
    send  "XXX\r"
    sleep 1

set argc 0
set argv0 "expect"
set argv ""

Update: The output of the second script posted by glenn is:

spawn zipcloak test.upd
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {9956}
Gate keeper glob pattern for 'password: $' is 'password: '. Activating booster.

expect: does "" (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=no
Enter password:
expect: does "Enter password: " (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=yes re=yes
expect: set expect_out(0,string) "password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "Enter password: "
send: sending "mypassword\r" to { exp6 }
expect: continuing expect

expect: does "" (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=no
mypassword

expect: does "mypassword\r\n" (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=no
expect: timed out
argv[0] = expect  argv[1] = -c  argv[2] =
    exp_internal 1
    spawn zipcloak test.upd
    expect {
        -re {password: $} {send "mypassword\r"; exp_continue}
        eof
    }

set argc 0
set argv0 "expect"
set argv ""

Update

I actually want to specify the filename and the password on the commandline to call the code as

./myscript.sh test.upd pass

Here is the script:

#!/bin/bash
expect -c " 
    exp_internal 1
    spawn zipcloak \"$1\"
    expect {
        -re {password: \$} {send \"$2\r\"; exp_continue}
        expect eof
    }
"

However, it creates again a file starting with zi and does not encrypt the actual file. I had no idea that every little seemingly logic change could break the entire workflow of the expect script. Here is the ouput:

spawn zipcloak test.upd
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {16791}
Gate keeper glob pattern for 'password: $' is 'password: '. Activating booster.

expect: does "" (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=no
"expect"? no
Enter password:
expect: does "Enter password: " (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=yes re=yes
expect: set expect_out(0,string) "password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "Enter password: "
send: sending "pass\r" to { exp6 }
expect: continuing expect

expect: does "" (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=no
"expect"? no
pass

expect: does "pass\r\n" (spawn_id exp6) match regular expression "password: $"? Gate "password: "? gate=no
"expect"? no
expect: timed out
argv[0] = expect  argv[1] = -c  argv[2] =
    exp_internal 1
    spawn zipcloak "test.upd"
    expect {
        -re {password: $} {send "pass\r"; exp_continue}
        expect eof
    }

set argc 0
set argv0 "expect"
set argv ""
  • I just increased the sleep time to '2' and now it seems to work. But why is that? Does the sleep time depend on how long I have this crap installed on my system? Does it depend on the daytime? On the comets that fell into the sun...? This is the most confusing problem I ever encountered... Should I use a value of 1000 just to be sure? – Alex Nov 29 '13 at 10:27
  • If you have correct expect patterns you should not have to sleep at all. While you're developing, add exp_internal 1 command somewhere before the spawn command. – glenn jackman Nov 29 '13 at 13:07
  • @Alex, you have to wait for zipcloak to finish which expect eof as in glen's solution or wait (or ideally both) should take care of. – Stéphane Chazelas Dec 3 '13 at 14:39
  • I have replaced sleep 1 with eof which gave an error. wrong # args: should be "eof channelId" while executing "eof" – Alex Dec 3 '13 at 16:25
  • eof is a pattern, so you want expect eof – glenn jackman Dec 3 '13 at 16:37
4

I'd write that zipcloak-er as

#!/usr/bin/env expect
set zipfile [lindex $argv 0]
if {![file exists $zipfile]} {error "no such zipfile: $zipfile"}
set pass "mypassword"
spawn zipcloak $zipfile
expect {
    -re {password: $} {send "$pass\r"; exp_continue}
    eof
}

Since the "enter password: " and "verify password: " prompts have a common suffix, it makes sense to use exp_continue to reuse the code.


"does not work" is not helpful. Did you use exp_internal 1? Try this:

#!/bin/bash
MYPWD="mypassword"

expect -c " 
    exp_internal 1
    spawn zipcloak test.upd
    expect {
        -re {password: \$} {send \"$MYPWD\\r\"; exp_continue}
        eof
    }
"

Sorry Alex, I don't understand your issue. This is what happens for me in bash:

$ zip test.upd file
  adding: file (deflated 22%)
$ MYPWD="mypassword"
$ expect -c " 
    exp_internal 1
    spawn zipcloak test.upd
    expect {
        -re {password: \$} {send \"$MYPWD\\r\"; exp_continue}
        eof
    }
"
spawn zipcloak test.upd
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {27485}
Gate keeper glob pattern for 'password: $' is 'password: '. Activating booster.

expect: does "" (spawn_id exp4) match regular expression "password: $"? Gate "password: "? gate=no
Enter password: 
expect: does "Enter password: " (spawn_id exp4) match regular expression "password: $"? Gate "password: "? gate=yes re=yes
expect: set expect_out(0,string) "password: "
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "Enter password: "
send: sending "mypassword\r" to { exp4 }
expect: continuing expect

expect: does "" (spawn_id exp4) match regular expression "password: $"? Gate "password: "? gate=no

Verify password: 
expect: does "\r\nVerify password: " (spawn_id exp4) match regular expression "password: $"? Gate "password: "? gate=yes re=yes
expect: set expect_out(0,string) "password: "
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "\r\nVerify password: "
send: sending "mypassword\r" to { exp4 }
expect: continuing expect

expect: does "" (spawn_id exp4) match regular expression "password: $"? Gate "password: "? gate=no


expect: does "\r\n" (spawn_id exp4) match regular expression "password: $"? Gate "password: "? gate=no
encrypting: file

expect: does "\r\nencrypting: file\r\n" (spawn_id exp4) match regular expression "password: $"? Gate "password: "? gate=no
expect: read eof
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "\r\nencrypting: file\r\n"
argv[0] = expect  argv[1] = -c  argv[2] =  
    exp_internal 1
    spawn zipcloak test.upd
    expect {
        -re {password: $} {send "mypassword\r"; exp_continue}
        eof
    }

set argc 0
set argv0 "expect"
set argv ""
  • I am afraid your suggestion does not seem work. After about 10 seconds zipinfo shows the file in question is not encrypted, while an empty file is created in the same directory starting with the phrase 'zi' (like zi8H9A9b or ziwlvWI3). – Alex Nov 30 '13 at 7:38
  • Again, the above suggestion does not work for me. – Alex Dec 3 '13 at 9:45
  • @Alex, and what's the output of glenn's script? – Stéphane Chazelas Dec 3 '13 at 14:36
  • I have included the output in my question – Alex Dec 3 '13 at 16:29
  • Please see updated question... – Alex Dec 5 '13 at 6:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.