| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | package Debug::Fork::Tmux; | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 2 |  |  | 2 |  | 125639 | use strict; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 67 |  | 
| 15 | 2 |  |  | 2 |  | 10 | use warnings; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 72 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | our $VERSION = '1.000012'; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  |  | 
| 22 | 2 |  |  | 2 |  | 8 | use File::Spec; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 45 |  | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  |  | 
| 25 | 2 |  |  | 2 |  | 10 | use Cwd; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 233 |  | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 2 |  |  | 2 |  | 20 | use Carp; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 140 |  | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 2 |  |  | 2 |  | 1414 | use Debug::Fork::Tmux::Config; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 69 |  | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  |  | 
| 34 | 2 |  |  | 2 |  | 11 | use Const::Fast; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 13 |  | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | sub DB::get_fork_TTY { | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 0 |  |  | 0 | 0 | 0 | my $tty_name = Debug::Fork::Tmux::_spawn_tty(); | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 2 |  |  | 2 |  | 227 | no warnings qw/once/; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 1250 |  | 
| 55 | 0 |  |  |  |  | 0 | $DB::fork_TTY = $tty_name; | 
| 56 | 0 |  |  |  |  | 0 | return $tty_name; | 
| 57 |  |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | sub _spawn_tty { | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  |  | 
| 66 | 0 |  |  | 0 |  | 0 | my $window_id = _tmux_new_window(); | 
| 67 | 0 |  |  |  |  | 0 | my $tty_name  = _tmux_window_tty($window_id); | 
| 68 |  |  |  |  |  |  |  | 
| 69 | 0 |  |  |  |  | 0 | return $tty_name; | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | sub _tmux_new_window { | 
| 79 | 0 |  |  | 0 |  | 0 | my @cmd_to_read = ( | 
| 80 |  |  |  |  |  |  | Debug::Fork::Tmux::Config->get_config('tmux_fqfn'), | 
| 81 |  |  |  |  |  |  | split( | 
| 82 |  |  |  |  |  |  | /\s+/, Debug::Fork::Tmux::Config->get_config('tmux_cmd_neww') | 
| 83 |  |  |  |  |  |  | ), | 
| 84 |  |  |  |  |  |  | Debug::Fork::Tmux::Config->get_config('tmux_cmd_neww_exec'), | 
| 85 |  |  |  |  |  |  | ); | 
| 86 |  |  |  |  |  |  |  | 
| 87 | 0 |  |  |  |  | 0 | my $window_id = _read_from_cmd(@cmd_to_read); | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 0 |  |  |  |  | 0 | return $window_id; | 
| 90 |  |  |  |  |  |  | } | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | sub _tmux_window_tty { | 
| 98 | 0 |  |  | 0 |  | 0 | my $window_id = shift; | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 0 |  |  |  |  | 0 | my @cmd_to_read = ( | 
| 102 |  |  |  |  |  |  | Debug::Fork::Tmux::Config->get_config('tmux_fqfn'), | 
| 103 |  |  |  |  |  |  | split( /\s+/, Debug::Fork::Tmux::Config->get_config('tmux_cmd_tty') ), | 
| 104 |  |  |  |  |  |  | $window_id, | 
| 105 |  |  |  |  |  |  | ); | 
| 106 | 0 |  |  |  |  | 0 | my @tmux_cmd = (@cmd_to_read); | 
| 107 | 0 |  |  |  |  | 0 | my $tty_name = _read_from_cmd(@tmux_cmd); | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 0 |  |  |  |  | 0 | return $tty_name; | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | sub _read_from_cmd { | 
| 120 | 8 |  |  | 8 |  | 18229 | my @cmd_and_args = @_; | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 8 | 50 |  |  |  | 33038 | _croak_on_cmd( @cmd_and_args, "failed opening command: $!" ) | 
| 124 |  |  |  |  |  |  | unless open my $cmd_output_fh => '-|', | 
| 125 |  |  |  |  |  |  | @cmd_and_args; | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 8 | 100 | 33 |  |  | 35520 | _croak_on_cmd( @cmd_and_args, "didn't write a line" ) | 
|  |  |  | 33 |  |  |  |  | 
| 129 |  |  |  |  |  |  | unless defined($cmd_output_fh) | 
| 130 |  |  |  |  |  |  | and ( 0 != $cmd_output_fh ) | 
| 131 |  |  |  |  |  |  | and my $cmd_out = <$cmd_output_fh>; | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  |  | 
| 135 | 5 |  |  |  |  | 961 | my $read_rv = read $cmd_output_fh => my $buf, 1; | 
| 136 | 5 | 50 |  |  |  | 51 | _croak_on_cmd( @cmd_and_args, "failed reading command: $!/$buf" ) | 
| 137 |  |  |  |  |  |  | unless defined $read_rv; | 
| 138 | 5 | 100 |  |  |  | 134 | _croak_on_cmd( @cmd_and_args, "did not finish: $buf" ) | 
| 139 |  |  |  |  |  |  | unless 0 == $read_rv; | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  |  | 
| 142 | 3 |  |  |  |  | 15 | chomp $cmd_out; | 
| 143 | 3 | 100 |  |  |  | 47 | _croak_on_cmd( @cmd_and_args, "provided empty string" ) | 
| 144 |  |  |  |  |  |  | unless length $cmd_out; | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 2 |  |  |  |  | 350 | return $cmd_out; | 
| 147 |  |  |  |  |  |  | } | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | sub _croak_on_cmd { | 
| 158 | 8 |  |  | 8 |  | 9965 | my @cmd_args_msg = @_; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 8 | 50 |  |  |  | 96 | if ( defined $? ) { | 
| 161 | 8 |  |  |  |  | 35 | my $msg = ''; | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  |  | 
| 165 | 8 | 50 |  |  |  | 77 | if ( $? == -1 ) { | 
|  |  | 50 |  |  |  |  |  | 
| 166 | 0 |  |  |  |  | 0 | $msg = "failed to execute: $!"; | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | elsif ( $? & 127 ) { | 
| 171 | 0 | 0 |  |  |  | 0 | $msg = sprintf "child died with signal %d, %s coredump", | 
| 172 |  |  |  |  |  |  | ( $? & 127 ), ( $? & 128 ) ? 'with' : 'without'; | 
| 173 |  |  |  |  |  |  | } | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | else { | 
| 177 | 8 |  |  |  |  | 78 | $msg = sprintf "child exited with value %d", $? >> 8; | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  |  | 
| 182 | 8 |  |  |  |  | 27 | push @cmd_args_msg, $msg; | 
| 183 |  |  |  |  |  |  | } | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  |  | 
| 186 | 8 |  |  |  |  | 59 | my $croak_msg = "The command " . join ' ' => @cmd_args_msg; | 
| 187 | 8 |  |  |  |  | 603 | croak($croak_msg); | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | 1; | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | __END__ | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | =pod | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | =head1 NAME | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | Debug::Fork::Tmux - Makes fork() in debugger to open a new Tmux window | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | =head1 VERSION | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | This documentation refers to the module contained in the distribution C<Debug-Fork-Tmux> version 1.000012. | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | #!/usr/bin/perl -d | 
| 208 |  |  |  |  |  |  | # | 
| 209 |  |  |  |  |  |  | # ABSTRACT: Debug the fork()-contained code in this file | 
| 210 |  |  |  |  |  |  | # | 
| 211 |  |  |  |  |  |  | ## Works only under Tmux: http://tmux.sf.net | 
| 212 |  |  |  |  |  |  | # | 
| 213 |  |  |  |  |  |  | # Make fork()s debuggable with Tmux | 
| 214 |  |  |  |  |  |  | use Debug::Fork::Tmux; | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | # See what happens in your debugger then... | 
| 217 |  |  |  |  |  |  | fork; | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | Make sure you have the running C<Tmux> window manager: | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | $ tmux | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | =over | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | =item * Only C<Tmux> version 1.6 and higher works with C<Debug::Fork::Tmux>. | 
| 228 |  |  |  |  |  |  | See L</DEPENDENCIES>. | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | =item * It is not necessary to run this under C<Tmux>, see L</Attaching to | 
| 231 |  |  |  |  |  |  | the other C<Tmux> session>. | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | =back | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | Then the real usage example of this module is: | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | $ perl -MDebug::Fork::Tmux -d your_script.pl | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | As Perl's standard debugger requires additional code to be written and used | 
| 240 |  |  |  |  |  |  | when the debugged Perl program use the L<fork()|perlfunc/fork> built-in. | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | This module is about to solve the trouble which is used to be observed like | 
| 243 |  |  |  |  |  |  | this: | 
| 244 |  |  |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | ######### Forked, but do not know how to create a new TTY. ######### | 
| 246 |  |  |  |  |  |  | Since two debuggers fight for the same TTY, input is severely entangled. | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | I know how to switch the output to a different window in xterms, OS/2 | 
| 249 |  |  |  |  |  |  | consoles, and Mac OS X Terminal.app only.  For a manual switch, put the | 
| 250 |  |  |  |  |  |  | name of the created TTY in $DB::fork_TTY, or define a function | 
| 251 |  |  |  |  |  |  | DB::get_fork_TTY() returning this. | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | On UNIX-like systems one can get the name of a TTY for the given window | 
| 254 |  |  |  |  |  |  | by typing tty, and disconnect the shell from TTY by sleep 1000000. | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | All of that is about getting the pseudo-terminal device for another part of | 
| 257 |  |  |  |  |  |  | user interface. This is probably why only the C<GUI>s are mentioned here: | 
| 258 |  |  |  |  |  |  | C<OS/2> 'Command Prompt', C<Mac OS X>'s C<Terminal.app> and an C<xterm>. For | 
| 259 |  |  |  |  |  |  | those of you who develop server-side stuff it should be known that keeping | 
| 260 |  |  |  |  |  |  | C<GUI> on the server is far from always to be available as an option no | 
| 261 |  |  |  |  |  |  | matter if it's a production or a development environment. | 
| 262 |  |  |  |  |  |  |  | 
| 263 |  |  |  |  |  |  | The most ridiculous for every C<TUI> (the C<ssh> particularly) user is that | 
| 264 |  |  |  |  |  |  | the pseudo-terminal device isn't that much about C<GUI>s by its nature so | 
| 265 |  |  |  |  |  |  | the problem behind the bars of the L<perl5db.pl> report (see more detailed | 
| 266 |  |  |  |  |  |  | problem description at the L<PerlMonks | 
| 267 |  |  |  |  |  |  | thread|http://perlmonks.org/?node_id=128283>) is the consoles management. | 
| 268 |  |  |  |  |  |  | It's a kind of a tricky, for example, to start the next C<ssh> session | 
| 269 |  |  |  |  |  |  | initiated from the machine serving as an C<sshd> server for the existing | 
| 270 |  |  |  |  |  |  | session. | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | Thus we kind of have to give a chance to the consoles management with a | 
| 273 |  |  |  |  |  |  | software capable to run on a server machine without as much dependencies as | 
| 274 |  |  |  |  |  |  | an C<xterm>. This module is a try to pick the L<Tmux|http://tmux.sf.net> | 
| 275 |  |  |  |  |  |  | windows manager for such a task. | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | Because of highly-developed scripting capabilities of C<Tmux> any user can | 
| 278 |  |  |  |  |  |  | supply the 'window' or a 'pane' to Perl's debugger making it suitable to | 
| 279 |  |  |  |  |  |  | debug the separate process in a different C<UI> instance. Also this adds the | 
| 280 |  |  |  |  |  |  | features like C<groupware>: imagine that your mate can debug the process | 
| 281 |  |  |  |  |  |  | you've just C<fork()ed> by mean of attaching the same C<tmux> you are | 
| 282 |  |  |  |  |  |  | running on a server. While you keep working on a process that called a | 
| 283 |  |  |  |  |  |  | C<fork()>. | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | =head1 SUBROUTINES/METHODS | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | All of the following are functions: | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | =head2 PUBLIC | 
| 290 |  |  |  |  |  |  |  | 
| 291 |  |  |  |  |  |  | =head3 C<DB::get_fork_TTY()> | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | Finds new C<TTY> for the C<fork()>ed process. | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | Takes no arguments. Returns C<Str> name of the C<tty> device of the <tmux>'s | 
| 296 |  |  |  |  |  |  | new window created for the debugger's new process. | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | Sets the C<$DB::fork_TTY> to the same C<Str> value. | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | =head2 PRIVATE | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | =head3 C<_spawn_tty()> | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | Creates a C<TTY> device and returns C<Str> its name. | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | =head3 C<_tmux_new_window()> | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | Creates a given C<tmux> window and returns C<Str> its id/number. | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | =head3 C<_tmux_window_tty( $window_id )> | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | Finds a given C<tmux> window's tty name and returns its C<Str> name based on | 
| 313 |  |  |  |  |  |  | a given window id/number typically from L</_tmux_new_window()>. | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  | =head3 C<_read_from_cmd( $cmd =E<gt> @args )> | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | Takes the list containing the C<Str> L<system()|perlfunc/system> command and | 
| 318 |  |  |  |  |  |  | C<Array> its arguments and executes it. Reads C<Str> the output and returns it. | 
| 319 |  |  |  |  |  |  | Throws if no output or if the command failed. | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | =head3 C<_croak_on_cmd( $cmd =E<gt> @args, $happen )> | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | Takes the C<Str> command, C<Array> its arguments and C<Str> the reason of | 
| 324 |  |  |  |  |  |  | its failure, examines the C<$?> and dies with explanation on the | 
| 325 |  |  |  |  |  |  | L<system()|perlfunc/system> command failure. | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | =head1 CONFIGURATION AND ENVIRONMENT | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | The module requires the L<Tmux|http://tmux.sf.net> window manager for the | 
| 330 |  |  |  |  |  |  | console to be present in the system. | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | This means that it requires the C<Unix>-like operating system not only to | 
| 333 |  |  |  |  |  |  | have a L<fork> implemented and a C<TTY> device name supplement but the | 
| 334 |  |  |  |  |  |  | system should have Tmux up and running. | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | Therefore C<Cygwin> for example isn't in at this moment, see the | 
| 337 |  |  |  |  |  |  | L<explanation|http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1354> | 
| 338 |  |  |  |  |  |  | why. | 
| 339 |  |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | Configuration is made via environment variables, the default is taken for | 
| 341 |  |  |  |  |  |  | each of them with no such variable is set in the environment: | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | =head2 C<DFTMUX_FQFN> | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | The C<tmux> binary name with the full path. | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | Default :   The first of those for executable to exist: | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | =over | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | =item C<PATH> environment variable contents | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | =item Path to the Perl binary interpreter | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | =item Current directory | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | =back | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | and just the C<tmux> as a fallback if none of above is the location of the | 
| 360 |  |  |  |  |  |  | C<tmux> executable file. | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | =head2 C<DFTMUX_CMD_NEWW> | 
| 363 |  |  |  |  |  |  |  | 
| 364 |  |  |  |  |  |  | The L<system()|perlfunc/system> arguments for a C<tmux> | 
| 365 |  |  |  |  |  |  | command for opening a new window and with output of a window address from | 
| 366 |  |  |  |  |  |  | C<tmux>. String is sliced by spaces to be a list of parameters. | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | Default :  C<neww -P> | 
| 369 |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  | =head2 C<DFTMUX_CMD_NEWW_EXEC> | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | The L<system()|perlfunc/system> or a shell command to be given to the | 
| 373 |  |  |  |  |  |  | C<DFTMUX_CMD_NEWW> command to be executed in a brand new created | 
| 374 |  |  |  |  |  |  | window. It should wait unexpectedly and do nothing till the debugger | 
| 375 |  |  |  |  |  |  | catches the device and puts in into the proper use. | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | Default :  C<sleep 1000000> | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | =head2 C<DFTMUX_CMD_TTY> | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | Command- line  parameter(s) for a  C<tmux> command to find a C<tty> name in | 
| 382 |  |  |  |  |  |  | the output. The string is sliced then by spaces. The C<tmux>'s window | 
| 383 |  |  |  |  |  |  | address is added then as the very last argument. | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | Default :  C<lsp -F #{pane_tty} -t> | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | =head2 Earlier versions' C<SPUNGE_*> environment variables | 
| 388 |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  | Till v1.000009 the module was controlled by the environment variables like | 
| 390 |  |  |  |  |  |  | C<SPUNGE_TMUX_FQDN>. Those are deprecated and should be replaced in your | 
| 391 |  |  |  |  |  |  | configuration(s) onto the C<DFTMUX_>-prefixed ones. | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | =head2 Attaching to the other C<Tmux> session | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | For the case you can not or don't want to use the current C<tmux> session | 
| 396 |  |  |  |  |  |  | you are running in, you may want to have the separate C<tmux> server up and | 
| 397 |  |  |  |  |  |  | running and use its windows or panes to be created. This can be done by mean | 
| 398 |  |  |  |  |  |  | of prepending the correct C<-L> or C<-S> switch to the start of the every of | 
| 399 |  |  |  |  |  |  | the command-line parameters string to be used, for example: | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | $ DFTMUX_CMD_NEWW="-L default neww -P" \ | 
| 402 |  |  |  |  |  |  | > DFTMUX_CMD_TTY="-L default lsp -F #{pane_tty} -t" \ | 
| 403 |  |  |  |  |  |  | > perl -MDebug::Fork::Tmux -d your_script.pl | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | =head1 DIAGNOSTICS | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | =over | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | =item * C<The command ...> | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | Typically the error message starts with the command the L<Debug::Fork::Tmux> tried | 
| 412 |  |  |  |  |  |  | to execute, including the command's arguments. | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | =item * C<failed opening command: ...> | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | The command was not taken by the system as an executable binary file. | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | =item * C<... didn't write a line> | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | =item * C<failed reading command: ...> | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | Command did not output exactly one line of the text. | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | =item * C<... did not finish> | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | Command outputs more than one line of the text. | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | =item * C<provided empty string> | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | Command outputs exactly one line of the text and the line is empty. | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  | =item * C<failed to execute: ...> | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | There was failure executing the command | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | =item * C<child died with(out) signal X, Y coredump> | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | Command was killed by the signal X and the coredump is (not) located in Y. | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | =item * C<child exited with value X> | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | Command was not failed but there are reasons to throw an error like the | 
| 443 |  |  |  |  |  |  | wrong command's output. | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  | =back | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | =head1 DEPENDENCIES | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  | * C<Perl 5.8.9+> | 
| 450 |  |  |  |  |  |  | is available from L<The Perl website|http://www.perl.org> | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | * L<Config>, L<Cwd>, L<DB>, L<ExtUtils::MakeMaker>, L<File::Find>, | 
| 453 |  |  |  |  |  |  | L<File::Spec>, L<File::Basename>, L<Scalar::Util>, L<Test::More> are | 
| 454 |  |  |  |  |  |  | available in core C<Perl> distribution version 5.8.9 and later | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | * L<Const::Fast> | 
| 457 |  |  |  |  |  |  | is available from C<CPAN> | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | * L<Module::Build> | 
| 460 |  |  |  |  |  |  | is available in core C<Perl> distribution since version 5.9.4 | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | * L<Sort::Versions> | 
| 463 |  |  |  |  |  |  | is available from C<CPAN> | 
| 464 |  |  |  |  |  |  |  | 
| 465 |  |  |  |  |  |  | * L<Test::Exception> | 
| 466 |  |  |  |  |  |  | is available from C<CPAN> | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | * L<Test::Most> | 
| 469 |  |  |  |  |  |  | is available from C<CPAN> | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | * L<Test::Strict> | 
| 472 |  |  |  |  |  |  | is available from C<CPAN> | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  | * L<Env::Path> | 
| 475 |  |  |  |  |  |  | is available from C<CPAN> | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | * L<autodie> | 
| 478 |  |  |  |  |  |  | is available in core C<Perl> distribution since version 5.10.1 | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | * C<Tmux> v1.6+ | 
| 481 |  |  |  |  |  |  | is available from L<The Tmux website|http://tmux.sourceforge.net> | 
| 482 |  |  |  |  |  |  |  | 
| 483 |  |  |  |  |  |  | Most of them can easily be found in your operating system | 
| 484 |  |  |  |  |  |  | distribution/repository. | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | =head1 BUGS AND LIMITATIONS | 
| 487 |  |  |  |  |  |  |  | 
| 488 |  |  |  |  |  |  | You can make new bug reports, and view existing ones, through the | 
| 489 |  |  |  |  |  |  | web interface at L<http://bugs.vereshagin.org/product/Debug-Fork-Tmux>. | 
| 490 |  |  |  |  |  |  |  | 
| 491 |  |  |  |  |  |  | =head1 WEB SITE | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | The web site of | 
| 494 |  |  |  |  |  |  | L<Debug::Fork::Tmux|http://gitweb.vereshagin.org/Debug-Fork-Tmux/README.html> currently | 
| 495 |  |  |  |  |  |  | consists of only one page cause it's a very small module. | 
| 496 |  |  |  |  |  |  |  | 
| 497 |  |  |  |  |  |  | You may want to visit a L<GitHub | 
| 498 |  |  |  |  |  |  | page|https://github.com/petr999/Debug-Fork-Tmux>, too. | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  | =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | =head1 SUPPORT | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | =head2 Perldoc | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  | You can find documentation for this module with the perldoc command. | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | perldoc Debug::Fork::Tmux | 
| 509 |  |  |  |  |  |  |  | 
| 510 |  |  |  |  |  |  | =head2 Websites | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | The following websites have more information about this module, and may be of help to you. As always, | 
| 513 |  |  |  |  |  |  | in addition to those websites please use your favorite search engine to discover more resources. | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  | =over 4 | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  | =item * | 
| 518 |  |  |  |  |  |  |  | 
| 519 |  |  |  |  |  |  | MetaCPAN | 
| 520 |  |  |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | A modern, open-source CPAN search engine, useful to view POD in HTML format. | 
| 522 |  |  |  |  |  |  |  | 
| 523 |  |  |  |  |  |  | L<http://metacpan.org/release/Debug-Fork-Tmux> | 
| 524 |  |  |  |  |  |  |  | 
| 525 |  |  |  |  |  |  | =item * | 
| 526 |  |  |  |  |  |  |  | 
| 527 |  |  |  |  |  |  | Search CPAN | 
| 528 |  |  |  |  |  |  |  | 
| 529 |  |  |  |  |  |  | The default CPAN search engine, useful to view POD in HTML format. | 
| 530 |  |  |  |  |  |  |  | 
| 531 |  |  |  |  |  |  | L<http://search.cpan.org/dist/Debug-Fork-Tmux> | 
| 532 |  |  |  |  |  |  |  | 
| 533 |  |  |  |  |  |  | =item * | 
| 534 |  |  |  |  |  |  |  | 
| 535 |  |  |  |  |  |  | RT: CPAN's Bug Tracker | 
| 536 |  |  |  |  |  |  |  | 
| 537 |  |  |  |  |  |  | The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. | 
| 538 |  |  |  |  |  |  |  | 
| 539 |  |  |  |  |  |  | L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Debug-Fork-Tmux> | 
| 540 |  |  |  |  |  |  |  | 
| 541 |  |  |  |  |  |  | =item * | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | AnnoCPAN | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | The AnnoCPAN is a website that allows community annotations of Perl module documentation. | 
| 546 |  |  |  |  |  |  |  | 
| 547 |  |  |  |  |  |  | L<http://annocpan.org/dist/Debug-Fork-Tmux> | 
| 548 |  |  |  |  |  |  |  | 
| 549 |  |  |  |  |  |  | =item * | 
| 550 |  |  |  |  |  |  |  | 
| 551 |  |  |  |  |  |  | CPAN Ratings | 
| 552 |  |  |  |  |  |  |  | 
| 553 |  |  |  |  |  |  | The CPAN Ratings is a website that allows community ratings and reviews of Perl modules. | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | L<http://cpanratings.perl.org/d/Debug-Fork-Tmux> | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | =item * | 
| 558 |  |  |  |  |  |  |  | 
| 559 |  |  |  |  |  |  | CPAN Forum | 
| 560 |  |  |  |  |  |  |  | 
| 561 |  |  |  |  |  |  | The CPAN Forum is a web forum for discussing Perl modules. | 
| 562 |  |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  | L<http://cpanforum.com/dist/Debug-Fork-Tmux> | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | =item * | 
| 566 |  |  |  |  |  |  |  | 
| 567 |  |  |  |  |  |  | CPANTS | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  | The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. | 
| 570 |  |  |  |  |  |  |  | 
| 571 |  |  |  |  |  |  | L<http://cpants.perl.org/dist/overview/Debug-Fork-Tmux> | 
| 572 |  |  |  |  |  |  |  | 
| 573 |  |  |  |  |  |  | =item * | 
| 574 |  |  |  |  |  |  |  | 
| 575 |  |  |  |  |  |  | CPAN Testers | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | The CPAN Testers is a network of smokers who run automated tests on uploaded CPAN distributions. | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | L<http://www.cpantesters.org/distro/D/Debug-Fork-Tmux> | 
| 580 |  |  |  |  |  |  |  | 
| 581 |  |  |  |  |  |  | =item * | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | CPAN Testers Matrix | 
| 584 |  |  |  |  |  |  |  | 
| 585 |  |  |  |  |  |  | The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | L<http://matrix.cpantesters.org/?dist=Debug-Fork-Tmux> | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | =item * | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | CPAN Testers Dependencies | 
| 592 |  |  |  |  |  |  |  | 
| 593 |  |  |  |  |  |  | The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | L<http://deps.cpantesters.org/?module=Debug::Fork::Tmux> | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | =back | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | =head2 Email | 
| 600 |  |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | You can email the author of this module at C<peter@vereshagin.org> asking for help with any problems you have. | 
| 602 |  |  |  |  |  |  |  | 
| 603 |  |  |  |  |  |  | =head2 Bugs / Feature Requests | 
| 604 |  |  |  |  |  |  |  | 
| 605 |  |  |  |  |  |  | Please report any bugs or feature requests by email to C<peter@vereshagin.org>, or through | 
| 606 |  |  |  |  |  |  | the web interface at L<http://bugs.vereshagin.org/product/Debug-Fork-Tmux>. You will be automatically notified of any | 
| 607 |  |  |  |  |  |  | progress on the request by the system. | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | =head2 Source Code | 
| 610 |  |  |  |  |  |  |  | 
| 611 |  |  |  |  |  |  | The code is open to the world, and available for you to hack on. Please feel free to browse it and play | 
| 612 |  |  |  |  |  |  | with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull | 
| 613 |  |  |  |  |  |  | from your repository :) | 
| 614 |  |  |  |  |  |  |  | 
| 615 |  |  |  |  |  |  | L<http://gitweb.vereshagin.org/Debug-Fork-Tmux> | 
| 616 |  |  |  |  |  |  |  | 
| 617 |  |  |  |  |  |  | git clone https://github.com/petr999/Debug-Fork-Tmux.git | 
| 618 |  |  |  |  |  |  |  | 
| 619 |  |  |  |  |  |  | =head1 AUTHOR | 
| 620 |  |  |  |  |  |  |  | 
| 621 |  |  |  |  |  |  | L<Peter Vereshagin|http://vereshagin.org> <peter@vereshagin.org> | 
| 622 |  |  |  |  |  |  |  | 
| 623 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 624 |  |  |  |  |  |  |  | 
| 625 |  |  |  |  |  |  | This software is Copyright (c) 2013 by Peter Vereshagin. | 
| 626 |  |  |  |  |  |  |  | 
| 627 |  |  |  |  |  |  | This is free software, licensed under: | 
| 628 |  |  |  |  |  |  |  | 
| 629 |  |  |  |  |  |  | The (three-clause) BSD License | 
| 630 |  |  |  |  |  |  |  | 
| 631 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 632 |  |  |  |  |  |  |  | 
| 633 |  |  |  |  |  |  | Please see those modules/websites for more information related to this module. | 
| 634 |  |  |  |  |  |  |  | 
| 635 |  |  |  |  |  |  | =over 4 | 
| 636 |  |  |  |  |  |  |  | 
| 637 |  |  |  |  |  |  | =item * | 
| 638 |  |  |  |  |  |  |  | 
| 639 |  |  |  |  |  |  | L<Debug::Fork::Tmux::Config|Debug::Fork::Tmux::Config> | 
| 640 |  |  |  |  |  |  |  | 
| 641 |  |  |  |  |  |  | =item * | 
| 642 |  |  |  |  |  |  |  | 
| 643 |  |  |  |  |  |  | L<http://perlmonks.org/?node_id=128283|http://perlmonks.org/?node_id=128283> | 
| 644 |  |  |  |  |  |  |  | 
| 645 |  |  |  |  |  |  | =item * | 
| 646 |  |  |  |  |  |  |  | 
| 647 |  |  |  |  |  |  | L<nntp://nntp.perl.org/perl.debugger|nntp://nntp.perl.org/perl.debugger> | 
| 648 |  |  |  |  |  |  |  | 
| 649 |  |  |  |  |  |  | =item * | 
| 650 |  |  |  |  |  |  |  | 
| 651 |  |  |  |  |  |  | L<http://debugger.perl.org/|http://debugger.perl.org/> | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  | =back | 
| 654 |  |  |  |  |  |  |  | 
| 655 |  |  |  |  |  |  | =head1 DISCLAIMER OF WARRANTY | 
| 656 |  |  |  |  |  |  |  | 
| 657 |  |  |  |  |  |  | BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | 
| 658 |  |  |  |  |  |  | FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT | 
| 659 |  |  |  |  |  |  | WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER | 
| 660 |  |  |  |  |  |  | PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, | 
| 661 |  |  |  |  |  |  | EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE | 
| 662 |  |  |  |  |  |  | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
| 663 |  |  |  |  |  |  | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE | 
| 664 |  |  |  |  |  |  | SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME | 
| 665 |  |  |  |  |  |  | THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. | 
| 666 |  |  |  |  |  |  |  | 
| 667 |  |  |  |  |  |  | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | 
| 668 |  |  |  |  |  |  | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | 
| 669 |  |  |  |  |  |  | REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE | 
| 670 |  |  |  |  |  |  | TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR | 
| 671 |  |  |  |  |  |  | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | 
| 672 |  |  |  |  |  |  | SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING | 
| 673 |  |  |  |  |  |  | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A | 
| 674 |  |  |  |  |  |  | FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF | 
| 675 |  |  |  |  |  |  | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 
| 676 |  |  |  |  |  |  | DAMAGES. | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  | =cut | 
| 679 |  |  |  |  |  |  |  |