1

I want to check, if a user has access rights to a certain samba-share. I'm currently doing this using the command smbclient in Version 4.3.11-Ubuntu.

Apparently it is not a good idea to use the exit status for evaluation of success, as described in this question: Exit codes of smbclient

But nevertheless I have some strange behaviour. I get different exit status when calling the program with Perls system function.

perldoc -f system tells me this:

The return value is the exit status of the program as returned by the "wait" call.

When calling from commandline I get EXIT 1

user@host:~$ smbclient //server/share MyFalsePassword --user=any.user -c "cd somefolder;"; echo "EXIT $?"
WARNING: The "syslog" option is deprecated
session setup failed: NT_STATUS_LOGON_FAILURE
EXIT 1

Calling the same whitin Perl I get EXIT 256.

user@host:~$ perl -E 'say "EXIT " . system("smbclient //server/share MyFalsePassword --user=any.user -c \"cd somefolder;\"");'
WARNING: The "syslog" option is deprecated
session setup failed: NT_STATUS_LOGON_FAILURE
EXIT 256

I also have the value 256 in the variable $? whitin Perl.

Note: I get EXIT 0 in both (Bash and Perl) if I use the correct credentials.

My question: Why do I get different exit status from Bash and Perl if I use wrong credentials? How do I check correctly?

I use Perl v5.22 on Ubuntu 16.04.

Boris Däppen
  • 1,186
  • 7
  • 20

2 Answers2

3

The exit status returned by system is a two-byte number, which packs the exit code returned by the program into high bits, while the low 8 bits are set if the process was killed by a signal. The low 7 bits are the signal number and the 8th bit shows whether the core was dumped.

So to get the actual exit of the program do as the next sentence from the docs you quote says

To get the actual exit value, shift right by eight

and 256 >> 8 gives us 1.

The system's return is available in the variable $?, interrogated as spelled out in system

if ($? == -1) {
    print "failed to execute: $!\n";
}
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
        ($? & 127),  ($? & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $? >> 8;
}

The return is best saved or $? examined right away, before it gets cleared.


The bit shifting can be avoided by using IPC::System::Simple, which returns the program's exit value directly. Thanks to daxim for the comment. To investigate the signal we still need $? but this comes up far less frequently. The module simplifies system and qx use and error checking.

zdim
  • 64,580
  • 5
  • 52
  • 81
  • This is unexpectetly complicated. Should be mentioned here: https://stackoverflow.com/questions/799968/whats-the-difference-between-perls-backticks-system-and-exec I have read the sentence you quoted before. Your explanation helps a lot understanding the docs. Thank you! Is there no module on CPAN, offering an interface which does not require bit-operations? This is a pain for anybody who needs to look at this code later on. – Boris Däppen Jul 20 '17 at 08:41
  • *"If the return from system is non-zero you can interrogate the variable $?"* There's no need to check `$?` as well as the return value from `system`: they are identical. – Borodin Jul 20 '17 at 09:02
  • @Borodin I meant to relate `$?` examination to what is most often done, `system(...) == 0 or ...` (or `system(...) and ...`). I mean people normally check the return of `system` first. It did come out a little clumsy perhaps :( – zdim Jul 20 '17 at 09:05
  • @BorisDäppen The link you mention discusses differences between calls that have status in `$?` so I'd say, yes, you are right to expect this to get mentioned. I am not aware of modules that would split out the command's actual exit, but there are many that wrap up `system` (or `qx`) to nicely give access to `STDOUT` and `STDERR`, check errors, etc. I'll look around ... – zdim Jul 20 '17 at 09:10
  • For everyone who thinks doing this arithmetics every time is stupid and should be abstracted away, see [allowed exit values in IPC::System::Simple](http://p3rl.org/IPC::System::Simple#Exit-values). – daxim Jul 20 '17 at 09:28
  • @BorisDäppen Added the link provided by daxim to the answer – zdim Jul 20 '17 at 20:40
  • @daxim Thank you, added to the answer – zdim Jul 20 '17 at 20:44
2

This isn't very well documented, and the most useful information is in perldoc perlvar which says this

  • $CHILD_ERROR
  • $?

    The status returned by the last pipe close, backtick command, successful call to wait() or waitpid(), or from the system() operator. This is just the 16-bit status word returned by the traditional Unix wait() system call (or else is made up to look like it). Thus, the exit value of the subprocess is really ($? >> 8 ), and $? & 127 gives which signal, if any, the process died from, and $? & 128 reports whether there was a core dump.

So a return value of 256 from system corresponds to an exit value of 256 >> 8, which is the 1 you were expecting

Borodin
  • 126,100
  • 9
  • 70
  • 144