System-Command-1.122/0000755000175000017500000000000014367550242013035 5ustar bookbookSystem-Command-1.122/LICENSE0000644000175000017500000004370614367550242014054 0ustar bookbookThis software is copyright (c) 2023 by Philippe Bruhat (BooK). This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2023 by Philippe Bruhat (BooK). This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2023 by Philippe Bruhat (BooK). This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End System-Command-1.122/Changes0000644000175000017500000001737714367550242014347 0ustar bookbookRevision history for System-Command 1.122 2023-02-04 BOOK [TESTS] - Use $^X in Perl tests, instead of 'perl' (RT #141674 by SREZIC) - Fix t/30-exit.t to pass on Windows (RT #133230 by Lisa Hansen) - Drop some author developement modules from BuildRequires (GH #30 by OALDERS) 1.121 2020-06-03 BOOK - No functional change: update Changes and contributors 1.120 2020-06-03 BOOK [ENHANCEMENTS] - System::Command does not clobber $? and $! any more when DESTOYed (GH #27 by MMCCLIMON) 1.119 Mon Apr 2 2018 [TESTS] - Various test fixes for Win32 and "perl in space" (ETJ) [DOCUMENTATION] - document the 'input_record_separator' option to loop_on() 1.118 Thu Jun 2 2016 [ENHANCEMENTS] - Avoid calling waitpid() more than necessary in _reap() - Close all pipes when loop_on() ends successfully, and avoid a warning when the exit value is not available [TESTS] - Fix t/20-zombie.t, which was broken in Strawberry Perl (viviparous) 1.117 Sun Jan 17 2016 [ENHANCEMENT] - New method loop_on() allows to run callbacks on the output/errput 1.116 Sun Jan 3 2016 [BUG FIX] - Fix for the 'interactive' option (RKINYON) [COMPATIBILITY] - Remove a warning that was showing up under Perl 5.6 1.115 Mon Sep 28 2015 [BUG FIX] - ensure test counts and skip counts remain tied together (MITHALDU) [DOCUMENTATION] - for each option/feature, document in which version it appeared 1.114 Fri Sep 18 2015 [ENHANCEMENTS] - added proper accessors for the following System::Command::Reaper attributes: sdtin, stdout, stderr, exit, signal, core (after discussion with TIMB in RT #106330) - added 'exit', 'signal', 'core' options to System::Command, to allow direct update of variables at reaping time - added the 'interactive' option, to make it possible to run interactive commands directly with system (after discussion with TIMB in RT #106330) 1.113 Sun Sep 6 2015 [ENHANCEMENTS] - add proper accessors for the following System::Command::Reaper attributes: sdtin, stdout, stderr, exit, signal, core (after discussion with TIMB in RT #106330) - System::Command::close() now returns the object itself (RT #106867) [DOCUMENTATION] - document the return value of close() can be used to access the value of exit, signal and core 1.112 Sat Jul 25 2015 [ENHANCEMENTS] - the 'trace' option now also outputs some information about process termination and status (as requested by TIMB in RT #106046) 1.111 Sat Feb 14 2015 [ENHANCEMENTS] - throw an error on empty string env variables on Win32 (MITHALDU) (RT #99824) [DOCUMENTATION] - minor documentation improvements - added the list of contributors to the META file 1.110 Wed Aug 27 2014 [ENHANCEMENTS] - the 'setpgrp' option can be used to enable/disable the call to setpgrp() in the spawned process [TESTS] - t/10-command.t now ignores environment variables set by ConEmu 1.109 Wed Jul 2 2014 [BUG FIX] - fix the test failures on Solaris, thanks to Wolfgang Pecho (RT #82857). The reaper code was actually buggy (since v1.03!) and only accidentally worked on platforms where WNOHANG == 1 (which was most of them) 1.108 Wed Feb 26 2014 [ENHANCEMENTS] - the 'trace' option makes it possible to see exactly which commands were spawned, with their options (including environment) [DOCUMENTATION] - style fixes 1.107 Sun Oct 20 2013 [ENHANCEMENTS] - zombies do not exist under Win32, so no need to warn about waitpid return value (many thanks to MITHALDU for his continued help in testing on this platform) [DOCUMENTATION] - removed duplicated NAME section [FUN] - more zombie quotes in System::Command::Reaper comments 1.106 Sat Oct 12 2013 [ENHANCEMENTS] - brought back System::Command::Reaper, which properly deals with zombies - execute the command in its own process group whenever possible (thanks to Vincent Pit) [TESTS] - test for the zombie processes is not TODO anymore - tests for the timely destruction of the reaper are back 1.105 Sat Oct 5 2013 [TESTS] - add a TODO test for the zombie processes created in certain cases - various other test improvements 1.104 Thu Sep 12 2013 [ENHANCEMENTS] - fixed for Perl versions < 5.8.9 [DOCUMENTATION] - minor documentation improvements [PACKAGING] - switch to Dist::Zilla for maintaining the distribution 1.103 Mon Jul 29 2013 [ENHANCEMENTS] - rewrote the _spawn code to work properly under Plack - version 1.100 and 1.102 re-introduced old bugs: they have been squished again, and tests fixed to prevent re-re-introduction 1.102 Fri Jul 26 2013 [ENHANCEMENTS] - ported an older fix from Git::Repository, to make System::Command work with modules that do bad things to STDIN, STDOUT and STDERR (thanks to Todd Rinaldo for his 2010 patch to Git::Repository) [work done during the patch -p0 hackathon] 1.101 Thu Jul 11 2013 [TESTS] - various minor test improvements (thanks to Oleg Gashev and mokko) [DOCUMENTATION] - minor documentation improvements 1.100 Sun Apr 14 2013 [ENHANCEMENTS] - use a IPC::Run-based implementation on Win32 - thanks to a lot of testing help from Christian Walde (MITHALDU) the test suite passes on Win32 - while working on this, we established that kill 0, $pid is broken under Win32 (reported to the perl5-porters mailing-list via ) 1.09 Sun Dec 9 2012 [ENHANCEMENTS] - list all dependencies and the github public repo in the META files (RT #81302) - use Symbol::gensym to create anonumous GLOBs (github #4) 1.08 Mon Nov 26 2012 [ENHANCEMENTS] - remove a superfluous eval {} that was hiding open3 exception (RT #80171) - set a handler for the PIPE signal only if Perl knows about it 1.07 Wed Apr 18 03:00:50 CEST 2012 [TESTS] - t/20-zombie.t sometimes failed because of a race condition. I'm now testing my assumptions, make the test in question a little bit useless, and closing RT #74959 1.06 Sun Jan 8 00:36:40 CET 2012 [ENHANCEMENTS] - add tests that show that I don't understand what I'm doing with STDIN/OUT/ERR, and remove the offending code (RT #73614) 1.05 Fri Jul 8 09:16:25 CEST 2011 [ENHANCEMENTS] - make spawn() work properly with subclasses 1.04 Tue Jun 7 00:47:13 CEST 2011 [ENHANCEMENTS] - allow removing variables from the environment by setting keys with an 'undef' value in the 'env' option [TESTS] - tests for the import options - added tests that were created for version 1.02 to the MANIFEST 1.03 Thu Mar 17 22:47:38 CET 2011 [ENHANCEMENTS] - removed all the System::Command::Reaper logic which, while being really nice, didn't actually add any value, and made things more complex 1.02 Tue Mar 15 20:27:29 CET 2011 [FEATURES] - new method is_terminated() allows to inquire about the child process state [ENHANCEMENTS] - added a relatively sane behaviour when a SIGCHLD handler exists - warns when such a SIGCHLD handler may prevent prevent the capture of status information at the death of a child process - added a -quiet option to silence the warning - ported fixes from Git::Repository to work with modules that do bad things to STDIN, STDOUT and STDERR (thanks to Todd Rinaldo) 1.01 Tue Feb 1 00:13:33 CET 2011 [FEATURES] - new shortcut class method: spawn() 1.00 Wed Jan 20 00:50:17 CET 2011 [FEATURES] - Generic version of the Git::Repository::Command process spawner [BUGS] - No work has been put on the Win32 version yet. System-Command-1.122/Makefile.PL0000644000175000017500000000336314367550242015014 0ustar bookbook# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.024. use strict; use warnings; use 5.006; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Object for running system commands", "AUTHOR" => "Philippe Bruhat (BooK) ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "System-Command", "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.006", "NAME" => "System::Command", "PREREQ_PM" => { "Carp" => 0, "Cwd" => 0, "Data::Dumper" => 0, "Fcntl" => 0, "IO::Handle" => 0, "IO::Select" => 0, "IPC::Run" => 0, "List::Util" => 0, "POSIX" => 0, "Scalar::Util" => 0, "Symbol" => 0, "constant" => 0, "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "Test::More" => "0.88" }, "VERSION" => "1.122", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Cwd" => 0, "Data::Dumper" => 0, "ExtUtils::MakeMaker" => 0, "Fcntl" => 0, "File::Spec" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IO::Select" => 0, "IPC::Open3" => 0, "IPC::Run" => 0, "List::Util" => 0, "POSIX" => 0, "Scalar::Util" => 0, "Symbol" => 0, "Test::More" => "0.88", "constant" => 0, "strict" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); System-Command-1.122/dist.ini0000644000175000017500000000414014367550242014500 0ustar bookbook; the basics name = System-Command author = Philippe Bruhat (BooK) license = Perl_5 copyright_holder = Philippe Bruhat (BooK) ; copyright_year = 2010-2020 ; file modifiers [PkgVersion] [PodVersion] ; file generators [ManifestSkip] [Manifest] [License] [MakeMaker] [PruneCruft] [PruneFiles] filename = setup match = \.patch$ match = mess/.* match = cover_db [GatherDir] ; metadata [MetaYAML] [MetaJSON] [AutoPrereqs] [Prereqs] [Prereqs / TestRequires] Test::More = 0.88 [Prereqs / TestRecommends] Test::Command = Test::Output = [ExecDir] [ShareDir] [Keywords] keywords = system command [MetaResources] repository.web = http://github.com/book/System-Command repository.url = http://github.com/book/System-Command.git repository.type = git bugtracker.web = http://rt.cpan.org/NoAuth/Bugs.html?Dist=System-Command bugtracker.mailto = bug-system-command@rt.cpan.org [MetaProvides::Package] [Meta::Contributors] contributor = Olaf Alders contributor = Lisa Hansen contributor = Slaven Rezić contributor = Michael McClimon contributor = Ed J contributor = viviparous contributor = Rob Kinyon contributor = Tim Bunce contributor = Oleg Gashev contributor = Christian Walde contributor = Vincent Pit contributor = Todd Rinaldo contributor = pecho contributor = Olivier Mengué contributor = mokko contributor = Alessandro Ghedini ; tests [MetaTests] [ExtraTests] [Test::ReportPrereqs] [Test::Compile] [PodSyntaxTests] [PodCoverageTests] ; release [NextRelease] format = %v %{yyyy-MM-dd}d %P [Git::NextVersion] [TestRelease] [ConfirmRelease] [UploadToCPAN] ; git [Git::Check] [Git::Commit] commit_msg = Changes for version %v changelog = Changes [Git::Tag] tag_format = v%v tag_message = %N v%v [Git::Push] push_to = origin push_to = github System-Command-1.122/META.yml0000644000175000017500000000353714367550242014316 0ustar bookbook--- abstract: 'Object for running system commands' author: - 'Philippe Bruhat (BooK) ' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' File::Temp: '0' IO::Handle: '0' IPC::Open3: '0' Test::More: '0.88' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010' keywords: - system - command license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: System-Command provides: System::Command: file: lib/System/Command.pm version: '1.122' System::Command::Reaper: file: lib/System/Command/Reaper.pm version: '1.122' requires: Carp: '0' Cwd: '0' Data::Dumper: '0' Fcntl: '0' IO::Handle: '0' IO::Select: '0' IPC::Run: '0' List::Util: '0' POSIX: '0' Scalar::Util: '0' Symbol: '0' constant: '0' perl: '5.006' strict: '0' warnings: '0' resources: bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=System-Command repository: http://github.com/book/System-Command.git version: '1.122' x_contributors: - 'Olaf Alders ' - 'Lisa Hansen ' - 'Slaven Rezić ' - 'Michael McClimon ' - 'Ed J ' - 'viviparous ' - 'Rob Kinyon ' - 'Tim Bunce ' - 'Oleg Gashev ' - 'Christian Walde ' - 'Vincent Pit ' - 'Todd Rinaldo ' - 'pecho ' - 'Olivier Mengué ' - 'mokko ' - 'Alessandro Ghedini ' x_generated_by_perl: v5.32.1 x_serialization_backend: 'YAML::Tiny version 1.73' x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later' System-Command-1.122/META.json0000644000175000017500000000633014367550242014460 0ustar bookbook{ "abstract" : "Object for running system commands", "author" : [ "Philippe Bruhat (BooK) " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010", "keywords" : [ "system", "command" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "System-Command", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::CPAN::Meta" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08" } }, "runtime" : { "requires" : { "Carp" : "0", "Cwd" : "0", "Data::Dumper" : "0", "Fcntl" : "0", "IO::Handle" : "0", "IO::Select" : "0", "IPC::Run" : "0", "List::Util" : "0", "POSIX" : "0", "Scalar::Util" : "0", "Symbol" : "0", "constant" : "0", "perl" : "5.006", "strict" : "0", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900", "Test::Command" : "0", "Test::Output" : "0" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Test::More" : "0.88" } } }, "provides" : { "System::Command" : { "file" : "lib/System/Command.pm", "version" : "1.122" }, "System::Command::Reaper" : { "file" : "lib/System/Command/Reaper.pm", "version" : "1.122" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-system-command@rt.cpan.org", "web" : "http://rt.cpan.org/NoAuth/Bugs.html?Dist=System-Command" }, "repository" : { "type" : "git", "url" : "http://github.com/book/System-Command.git", "web" : "http://github.com/book/System-Command" } }, "version" : "1.122", "x_contributors" : [ "Olaf Alders ", "Lisa Hansen ", "Slaven Rezi\u0107 ", "Michael McClimon ", "Ed J ", "viviparous ", "Rob Kinyon ", "Tim Bunce ", "Oleg Gashev ", "Christian Walde ", "Vincent Pit ", "Todd Rinaldo ", "pecho ", "Olivier Mengu\u00e9 ", "mokko ", "Alessandro Ghedini " ], "x_generated_by_perl" : "v5.32.1", "x_serialization_backend" : "Cpanel::JSON::XS version 4.25", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } System-Command-1.122/README0000644000175000017500000000401714367550242013717 0ustar bookbookNAME System::Command - Object for running system commands SYNOPSIS use System::Command; # invoke an external command, and return an object $cmd = System::Command->new( @cmd ); # options can be passed as a hashref $cmd = System::Command->new( @cmd, \%option ); # $cmd is basically a hash, with keys / accessors $cmd->stdin(); # filehandle to the process stdin (write) $cmd->stdout(); # filehandle to the process stdout (read) $cmd->stderr(); # filehandle to the process stdout (read) $cmd->pid(); # pid of the child process # done! $cmd->close(); # exit information $cmd->exit(); # exit status $cmd->signal(); # signal $cmd->core(); # core dumped? (boolean) DESCRIPTION System::Command is a class that launches external system commands and return an object representing them, allowing to interact with them through their "STDIN", "STDOUT" and "STDERR" handles. INSTALLATION To install this module, run the following commands: perl Makefile.PL make make test make install Alternatively, to install with Module::Build, you can use the following commands: perl Build.PL ./Build ./Build test ./Build install SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc System::Command You can also look for information at: RT, CPAN's request tracker http://rt.cpan.org/NoAuth/Bugs.html?Dist=System-Command AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/System-Command CPAN Ratings http://cpanratings.perl.org/d/System-Command Search CPAN http://search.cpan.org/dist/System-Command/ LICENSE AND COPYRIGHT Copyright (C) 2010-2016 Philippe Bruhat (BooK) This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. System-Command-1.122/MANIFEST0000644000175000017500000000077014367550242014172 0ustar bookbook# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.024. Changes LICENSE MANIFEST META.json META.yml Makefile.PL README dist.ini lib/System/Command.pm lib/System/Command/Reaper.pm t/00-compile.t t/00-report-prereqs.dd t/00-report-prereqs.t t/01-load.t t/10-command.t t/11-spawn-fail.t t/15-scope.t t/20-zombie.t t/21-loop_on.t t/25-refopts.t t/30-exit.t t/90-command.t t/90-output.t t/author-distmeta.t t/author-pod-coverage.t t/author-pod-syntax.t t/fail.pl t/info.pl t/lines.pl System-Command-1.122/lib/0000755000175000017500000000000014367550242013603 5ustar bookbookSystem-Command-1.122/lib/System/0000755000175000017500000000000014367550242015067 5ustar bookbookSystem-Command-1.122/lib/System/Command/0000755000175000017500000000000014367550242016445 5ustar bookbookSystem-Command-1.122/lib/System/Command/Reaper.pm0000644000175000017500000001533614367550242020231 0ustar bookbookpackage System::Command::Reaper; $System::Command::Reaper::VERSION = '1.122'; use strict; use warnings; use 5.006; use Carp; use Scalar::Util qw( weaken reftype ); use POSIX ":sys_wait_h"; use constant MSWin32 => $^O eq 'MSWin32'; use constant HANDLES => qw( stdin stdout stderr ); use constant STATUS => qw( exit signal core ); for my $attr ( HANDLES ) { no strict 'refs'; *$attr = sub { return $_[0]{$attr} }; } for my $attr ( STATUS ) { no strict 'refs'; *$attr = sub { $_[0]->is_terminated(); return $_[0]{$attr} }; } sub new { my ($class, $command, $o) = @_; $o ||= {}; my $self = bless { %$o, command => $command }, $class; # copy/weaken the important keys @{$self}{ pid => HANDLES } = @{$command}{ pid => HANDLES }; weaken $self->{$_} for ( command => HANDLES ); return $self; } # this is necessary, because kill(0,pid) is misimplemented in perl core my $_is_alive = MSWin32 ? sub { return `tasklist /FO CSV /NH /fi "PID eq $_[0]"` =~ /^"/ } : sub { return kill 0, $_[0]; }; sub is_terminated { my ($self) = @_; my $pid = $self->{pid}; # Zed's dead, baby. Zed's dead. return $pid if !$_is_alive->($pid) and exists $self->{exit}; # If that is a re-animated body, we're gonna have to kill it. return $self->_reap(WNOHANG); } sub _reap { my ( $self, $flags ) = @_; $flags = 0 if ! defined $flags; my $pid = $self->{pid}; # REPENT/THE END IS/EXTREMELY/FUCKING/NIGH if ( !exists $self->{exit} and my $reaped = waitpid( $pid, $flags ) ) { # Well, it's a puzzle because, technically, you're not alive. my $zed = $reaped == $pid; carp "Child process already reaped, check for a SIGCHLD handler" if !$zed && !$System::Command::QUIET && !MSWin32; # What do you think? "Zombie Kill of the Week"? @{$self}{ STATUS() } = $zed ? ( $? >> 8, $? & 127, $? & 128 ) : ( -1, -1, -1 ); # Who died and made you fucking king of the zombies? if ( defined( my $cmd = $self->{command} ) ) { @{$cmd}{ STATUS() } = @{$self}{ STATUS() }; # I know you're here, because I can smell your brains. my $o = $cmd->{options}; defined reftype( $o->{$_} ) and reftype( $o->{$_} ) eq 'SCALAR' and ${ $o->{$_} } = $self->{$_} for STATUS(); } # I think it's safe to assume it isn't a zombie. print { $self->{th} } "System::Command xit[$pid]: ", join( ', ', map "$_: $self->{$_}", STATUS() ), "\n" if $self->{trace}; return $reaped; # It's dead, Jim! } # Look! It's moving. It's alive. It's alive... return; } sub close { my ($self) = @_; # close all pipes my ( $in, $out, $err ) = @{$self}{qw( stdin stdout stderr )}; $in and $in->opened and $in->close || carp "error closing stdin: $!"; $out and $out->opened and $out->close || carp "error closing stdout: $!"; $err and $err->opened and $err->close || carp "error closing stderr: $!"; # and wait for the child (if any) $self->_reap(); return $self; } sub DESTROY { my ($self) = @_; local $?; local $!; $self->close if !exists $self->{exit}; } 1; __END__ =pod =head1 NAME System::Command::Reaper - Reap processes started by System::Command =head1 VERSION version 1.122 =head1 SYNOPSIS This class is used for internal purposes. Move along, nothing to see here. =head1 DESCRIPTION The L objects delegate the reaping of child processes to System::Command::Reaper objects. This allows a user to create a L and discard it after having obtained one or more references to its handles connected to the child process. The typical use case looks like this: my $fh = System::Command->new( @cmd )->stdout(); The child process is reaped either through a direct call to C or when the command object and all its handles have been destroyed, thus avoiding zombies (which would be reaped by the system at the end of the main program). This is possible thanks to the following reference graph: System::Command | | | ^| v v v !| in out err !| ^| ^| ^| !| !v !v !v !v System::Command::Reaper Legend: | normal ref ! weak ref The System::Command::Reaper object acts as a sentinel, that takes care of reaping the child process when the original L and its filehandles have been destroyed (or when L C method is being called). =head1 METHODS System::Command::Reaper supports the following methods: =head2 new my $reaper = System::Command::Reaper->new( $cmd, \%extra ); Create a new System::Command::Reaper object attached to the L object passed as a parameter. An optional hash reference can be used to pass extra attributes to the object. =head2 close $reaper->close(); Close all the opened filehandles of the main L object, reaps the child process, and updates the main object with the status information of the child process. C calls C when the sentinel is being destroyed. =head2 is_terminated if ( $reaper->is_terminated ) {...} Returns a true value if the underlying process was terminated. If the process was indeed terminated, collects exit status, etc. =head2 Accessors The attributes of a System::Command::Reaper object are also accessible through a number of accessors. The object returned by C will have the following attributes defined (as copied from the L object that created the reaper): =over 4 =item pid The PID of the underlying command. =item stdin A filehandle opened in write mode to the child process' standard input. =item stdout A filehandle opened in read mode to the child process' standard output. =item stderr A filehandle opened in read mode to the child process' standard error output. =back After the call to C or after C returns true, the following attributes will be defined: =over 4 =item exit The exit status of the underlying command. =item core A boolean value indicating if the command dumped core. =item signal The signal, if any, that killed the command. =back =head1 AUTHOR Philippe Bruhat (BooK), C<< >> =head1 ACKNOWLEDGEMENTS This scheme owes a lot to Vincent Pit who on #perlfr provided the general idea (use a proxy to delay object destruction and child process reaping) with code examples, which I then adapted to my needs. =head1 COPYRIGHT Copyright 2010-2016 Philippe Bruhat (BooK), all rights reserved. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut System-Command-1.122/lib/System/Command.pm0000644000175000017500000005625414367550242017017 0ustar bookbookpackage System::Command; $System::Command::VERSION = '1.122'; use warnings; use strict; use 5.006; use Carp; use Cwd qw( cwd ); use IO::Handle; use Symbol (); use Scalar::Util qw( blessed reftype ); use List::Util qw( reduce ); use System::Command::Reaper; use Config; use Fcntl qw( F_GETFD F_SETFD FD_CLOEXEC ); # MSWin32 support use constant MSWin32 => $^O eq 'MSWin32'; require IPC::Run if MSWin32; our $QUIET = 0; # trace setup at startup my $_trace_opts = sub { my ( $trace, $file, $th ) = split /=/, shift, 2; open $th, '>>', $file or carp "Can't open $file: $!" if $file; $th ||= *STDERR; return ( $trace, $th ); }; my @trace; @trace = $_trace_opts->( $ENV{SYSTEM_COMMAND_TRACE} ) if $ENV{SYSTEM_COMMAND_TRACE}; sub import { my ( $class, @args ) = @_; my %arg = ( quiet => sub { $QUIET = 1 } ); for my $arg (@args) { $arg =~ s/^-//; # allow dashed options croak "Unknown option '$arg' in 'use System::Command'" if !exists $arg{$arg}; $arg{$arg}->(); } } # a few simple accessors { no strict 'refs'; for my $attr (qw( pid stdin stdout stderr options )) { *$attr = sub { return $_[0]{$attr} }; } for my $attr (qw( exit signal core )) { no strict 'refs'; *$attr = sub { $_[0]->is_terminated(); return $_[0]{$attr} }; } for my $attr (qw( cmdline )) { *$attr = sub { return @{ $_[0]{$attr} } }; } } # REALLY PRIVATE FUNCTIONS # a sub-process spawning function my $_spawn = sub { my ($o, @cmd) = @_; my $pid; # setup filehandles my $in = Symbol::gensym; my $out = Symbol::gensym; my $err = Symbol::gensym; # no buffering on pipes used for writing select( ( select($in), $| = 1 )[0] ); # start the command if (MSWin32) { $pid = IPC::Run::start( [@cmd], ' $in, '>pipe' => $out, '2>pipe' => $err, ); } else { # the code below takes inspiration from IPC::Open3 and Sys::Cmd # create handles for the child process (using CAPITALS) my $IN = Symbol::gensym; my $OUT = Symbol::gensym; my $ERR = Symbol::gensym; # no buffering on pipes used for writing select( ( select($OUT), $| = 1 )[0] ); select( ( select($ERR), $| = 1 )[0] ); # connect parent and child with pipes pipe $IN, $in or croak "input pipe(): $!"; pipe $out, $OUT or croak "output pipe(): $!"; pipe $err, $ERR or croak "errput pipe(): $!"; # an extra pipe to communicate exec() failure pipe my ( $stat_r, $stat_w ); # create the child process $pid = fork; croak "Can't fork: $!" if !defined $pid; if ($pid) { # parent won't use those handles close $stat_w; close $IN; close $OUT; close $ERR; # failed to fork+exec? my $mesg = do { local $/; <$stat_r> }; die $mesg if $mesg; } else { # kid # use $stat_r to communicate errors back to the parent eval { # child won't use those handles close $stat_r; close $in; close $out; close $err; # setup process group if possible setpgrp 0, 0 if $o->{setpgrp} && $Config{d_setpgrp}; # close $stat_w on exec my $flags = fcntl( $stat_w, F_GETFD, 0 ) or croak "fcntl GETFD failed: $!"; fcntl( $stat_w, F_SETFD, $flags | FD_CLOEXEC ) or croak "fcntl SETFD failed: $!"; # associate STDIN, STDOUT and STDERR to the pipes my ( $fd_IN, $fd_OUT, $fd_ERR ) = ( fileno $IN, fileno $OUT, fileno $ERR ); open \*STDIN, "<&=$fd_IN" or croak "Can't open( \\*STDIN, '<&=$fd_IN' ): $!"; open \*STDOUT, ">&=$fd_OUT" or croak "Can't open( \\*STDOUT, '<&=$fd_OUT' ): $!"; open \*STDERR, ">&=$fd_ERR" or croak "Can't open( \\*STDERR, '<&=$fd_ERR' ): $!"; # and finally, exec into @cmd exec( { $cmd[0] } @cmd ) or do { croak "Can't exec( @cmd ): $!"; } }; # something went wrong print $stat_w $@; close $stat_w; # DIE DIE DIE eval { require POSIX; POSIX::_exit(255); }; exit 255; } } return ( $pid, $in, $out, $err ); }; my $_dump_ref = sub { require Data::Dumper; # only load if needed local $Data::Dumper::Indent = 0; local $Data::Dumper::Purity = 0; local $Data::Dumper::Maxdepth = 0; local $Data::Dumper::Quotekeys = 0; local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Useqq = 1; local $Data::Dumper::Terse = 1; return Data::Dumper->Dump( [shift] ); }; my $_do_trace = sub { my ( $trace, $th, $pid, $cmd, $o ) = @_; print $th "System::Command cmd[$pid]: ", join( ' ', map /\s/ ? $_dump_ref->($_) : $_, @$cmd ), "\n"; print $th map "System::Command opt[$pid]: $_->[0] => $_->[1]\n", map [ $_ => $_dump_ref->( $o->{$_} ) ], grep { $_ ne 'env' } sort keys %$o if $trace > 1; print $th map "System::Command env[$pid]: $_->[0] => $_->[1]\n", map [ $_ => $_dump_ref->( $o->{env}{$_} ) ], keys %{ $o->{env} || {} } if $trace > 2; }; # module methods sub new { my ( $class, @cmd ) = @_; # split the args my @o = { setpgrp => 1 }; @cmd = grep { !( ref eq 'HASH' ? push @o, $_ : 0 ) } @cmd; # merge the option hashes my $o = reduce { +{ %$a, %$b, exists $a->{env} && exists $b->{env} ? ( env => { %{ $a->{env} }, %{ $b->{env} } } ) : () }; } @o; # open the trace file before changing directory my ( $trace, $th ); ( $trace, $th ) = $_trace_opts->( $o->{trace} ) if $o->{trace}; ( $trace, $th ) = @trace if @trace; # environment override # chdir to the expected directory my $orig = cwd; my $dest = defined $o->{cwd} ? $o->{cwd} : undef; if ( defined $dest ) { chdir $dest or croak "Can't chdir to $dest: $!"; } # keep changes to the environment local local %ENV = %ENV; # update the environment if ( exists $o->{env} ) { croak "ENV variables cannot be empty strings on Win32" if MSWin32 and grep { defined and !length } values %{ $o->{env} }; @ENV{ keys %{ $o->{env} } } = values %{ $o->{env} }; delete $ENV{$_} for grep { !defined $o->{env}{$_} } keys %{ $o->{env} }; } # interactive mode requested if ( $o->{interactive} ) { croak "Can't run command in interactive mode: not a terminal" unless -t STDIN; system { $cmd[0] } @cmd; my $self = bless { cmdline => [@cmd], options => $o, stdin => IO::Handle->new, stdout => IO::Handle->new, stderr => IO::Handle->new, exit => $? >> 8, signal => $? & 127, core => $? & 128, }, $class; defined reftype( $o->{$_} ) and reftype( $o->{$_} ) eq 'SCALAR' and ${ $o->{$_} } = $self->{$_} for qw( exit signal core ); return $self; } # start the command my ( $pid, $in, $out, $err ) = eval { $_spawn->( $o, @cmd ); }; # FIXME - better check error conditions if ( !defined $pid ) { $_do_trace->( $trace, $th, '!', \@cmd, $o ) if $trace; croak $@; } # trace is mostly a debugging tool $_do_trace->( $trace, $th, $pid, \@cmd, $o ) if $trace; # some input was provided if ( defined $o->{input} ) { local $SIG{PIPE} = sub { croak "Broken pipe when writing to: @cmd" } if $Config{sig_name} =~ /\bPIPE\b/; print {$in} $o->{input} if length $o->{input}; $in->close; } # chdir back to origin if ( defined $dest ) { chdir $orig or croak "Can't chdir back to $orig: $!"; } # create the object my $self = bless { cmdline => [@cmd], options => $o, pid => MSWin32 ? $pid->{KIDS}[0]{PID} : $pid, stdin => $in, stdout => $out, stderr => $err, ( _ipc_run => $pid )x!! MSWin32, }, $class; # create the subprocess reaper and link the handles and command to it ${*$in} = ${*$out} = ${*$err} = $self->{reaper} # typeglobs FTW = System::Command::Reaper->new( $self, { trace => $trace, th => $th } ); return $self; } sub spawn { my ( $class, @cmd ) = @_; return @{ $class->new(@cmd) }{qw( pid stdin stdout stderr )}; } sub loop_on { my $self = shift; # handle options and defaults my %args = ( stderr => sub { print STDERR shift }, @_ ); for my $which ( grep exists $args{$_}, qw( stdout stderr ) ) { if ( $args{$which} ) { croak "'$which' option must be a CODE reference" if reftype $args{$which} ne 'CODE'; } else { delete $args{$which}; } } # create an object for the class method if ( !ref $self ) { die "'command' attribute required by loop_on when used as a class method" if !exists $args{command}; $self = $self->new( @{ $args{command} } ); } require IO::Select; my $select = IO::Select->new( $self->stdout, $self->stderr ); local $/ = $args{input_record_separator} if exists $args{input_record_separator}; # loop until end of streams while ( my @ready = $select->can_read ) { for my $fh (@ready) { my $which = $fh == $self->stdout ? 'stdout' : 'stderr'; if ( defined( my $line = <$fh> ) ) { my $ret = 1; $ret = $args{$which}->($line) if exists $args{$which}; return if !$ret; } else { $select->remove($fh); $fh->close; } } } # close all pipes and wait for the child to terminate $self->close; # success in the Unix sense return defined $self->exit && $self->exit == 0; } # delegate those to the reaper (when there's one) sub is_terminated { return $_[0]{options}{interactive} ? 1 : $_[0]{reaper}->is_terminated(); } sub close { $_[0]{reaper}->close() unless $_[0]{options}{interactive}; return $_[0]; } 1; __END__ =pod =head1 NAME System::Command - Object for running system commands =head1 VERSION version 1.122 =head1 SYNOPSIS use System::Command; # invoke an external command, and return an object $cmd = System::Command->new( @cmd ); # options can be passed as a hashref $cmd = System::Command->new( @cmd, \%option ); # $cmd is basically a hash, with keys / accessors $cmd->stdin(); # filehandle to the process stdin (write) $cmd->stdout(); # filehandle to the process stdout (read) $cmd->stderr(); # filehandle to the process stdout (read) $cmd->pid(); # pid of the child process # find out if the child process died if ( $cmd->is_terminated() ) { # the handles are not closed yet # but $cmd->exit() et al. are available if it's dead } # done! $cmd->close(); # exit information $cmd->exit(); # exit status $cmd->signal(); # signal $cmd->core(); # core dumped? (boolean) # cut to the chase my ( $pid, $in, $out, $err ) = System::Command->spawn(@cmd); =head1 DESCRIPTION System::Command is a class that launches external system commands and return an object representing them, allowing to interact with them through their C, C and C handles. =head1 METHODS System::Command supports the following methods: =head2 new my $cmd = System::Command->new( @cmd ) Runs an external command using the list in C<@cmd>. If C<@cmd> contains a hash reference, it is taken as an I