Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Here is a little project I'd like a bit of feedback on.

Not to long ago Anony put up this node. It was a little frusterating to watch. Not only was the mistake a common, simple one, but little niggles of system got even BrowserUK. And frankly, who hasn't been bit by it, once or twice, early in their Perl career?

Another niggle is Perl's error vars. Which one to use, when? And, though system calls are rarely portable, almost no one ever remembers to mention $^E on the off chance that the asker is on a VMS, Win32, or OS/2 system.

Both these issues are tidied up in Perl 6. But who wants to wait that long?

So, Shell::DWIM is intended to clean up these little niggles in a consistent way. I hope that it gets itself established enough that we can all point to it whenever a similar question comes down the pipeline. First, a little documentation, as none is currently supplied.

Shell::DWIM currently has no export system, in order to keep things simple for me. It provides two features.

  1. Shell::DWIM::run - This function is a RWIM (return what I mean) replacement for system. It returns true for a succesful execution, false for a failure. It does not support system's indirect object features currently. Unlike system it captures the exception generated by passing it tainted data, and sets $Shell::DWIM::RUN_ERROR appropriately.
  2. $Shell::DWIM::RUN_ERROR - This special variable is set by calls to Shell::DWIM::run. It attempts to be whichever of the four Perl error variables you need, with a few caveats. First, it does not have the number/string magic of $! - it is always stringified. Second, it prefers extended OS errors to the C errno on systems that have extended error support (currently VMS, OS/2, and Win32).

Suggested use:

Shell::DWIM::run $shell_commands or die $Shell::DWIM::RUN_ERROR;

What I ask of the Monastery is a code review and comment. Here are my specific concerns (there are several):

  • run and $RUN_ERROR are terrible names - anyone have better ideas?
  • Currently run traps the exception caused by system $tainted_data. Should it?
  • On the same note, it localizes $@ anticipating that no one will expect the eval{} that run uses internally. Since the other error vars are set correctly, is this application of the Principle of Least Surprise a bit too waterbed like?
  • While there is little that goes on that might be suspect, there is a bit of code between system @_ and the use of $! and $^E (called $OS_ERROR internally). perlvar warns that $! should be used immediatly. Is there a danger there?
  • If $^E is supported, we use it instead of $!. Is this gonna bite anyone in the butt?
  • With a little case specific aliasing, $RUN_ERROR could be made to support $! special magic. But then it could be reset by things other than calls to run. What's your opinion?
  • And finally, How's My Hacking? I'm a bit of a hobbyist programmer, so my style hasn't really gelled yet. Is there anything grossly stupid in the code?

Speaking of which:

package Shell::DWIM; use warnings; use strict; our ($EVAL_ERROR, $CHILD_ERROR, $OS_ERROR, $RUN_ERROR); #Setup internal friendly error names *EVAL_ERROR = \$@; *CHILD_ERROR = \$?; if ($^O =~ /VMS|MSWin|OS\/2/) { #These systems support an extended OS +error message ($^E) *OS_ERROR = \$^E; #$OS_ERROR reflects that value if it e +xists. This clashes somwhat with English.pm } else { *OS_ERROR = \$!; } #The public function sub run { my ($return) = 0; local $EVAL_ERROR; #The eval here is a little unexpected, so we lo +calize $EVAL_ERROR so no one get's bitten eval { $return = (( system @_ ) == 0); }; if ($return) { $RUN_ERROR = undef; } else { SWITCH: { do { $RUN_ERROR = $EVAL_ERROR && last SWITCH } if $EVAL_E +RROR ; do { $RUN_ERROR = $CHILD_ERROR && last SWITCH } if $CHILD_ +ERROR > 0 ; do { $RUN_ERROR = "$OS_ERROR" && last SWITCH } if $CHILD_ +ERROR == -1; #String version of $OS_ERROR LAST_CASE: { $RUN_ERROR = "Exception, package CommandLine: system() fai +led, error unknown"} } } return $return; } 1; #Because you gotta
Cheers,
Erik

Light a man a fire, he's warm for a day. Catch a man on fire, and he's warm for the rest of his life. - Terry Pratchet


In reply to RFC: Shell::DWIM by erikharrison

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (3)
As of 2024-04-19 02:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found