OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [Integration_test/] [synthetic_sim/] [perl_lib/] [Proc/] [Background.pm] - Blame information for rev 56

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 56 alirezamon
package Proc::Background;
2
$Proc::Background::VERSION = '1.30';
3
# ABSTRACT: Generic interface to Unix and Win32 background process management
4
require 5.004_04;
5
 
6
use strict;
7
use Exporter;
8
use Carp;
9
use Cwd;
10
use Scalar::Util;
11
@Proc::Background::ISA       = qw(Exporter);
12
@Proc::Background::EXPORT_OK = qw(timeout_system);
13
 
14
# Determine if the operating system is Windows.
15
my $is_windows = $^O eq 'MSWin32';
16
my $weaken_subref = Scalar::Util->can('weaken');
17
 
18
# Set up a regular expression that tests if the path is absolute and
19
# if it has a directory separator in it.  Also create a list of file
20
# extensions of append to the programs name to look for the real
21
# executable.
22
my $is_absolute_re;
23
my $has_dir_element_re;
24
my $path_sep;
25
my @extensions = ('');
26
if ($is_windows) {
27
  $is_absolute_re     = '^(?:(?:[a-zA-Z]:[\\\\/])|(?:[\\\\/]{2}\w+[\\\\/]))';
28
  $has_dir_element_re = "[\\\\/]";
29
  $path_sep           = "\\";
30
  push(@extensions, '.exe');
31
} else {
32
  $is_absolute_re     = "^/";
33
  $has_dir_element_re = "/";
34
  $path_sep           = "/";
35
}
36
 
37
# Make this class a subclass of Proc::Win32 or Proc::Unix.  Any
38
# unresolved method calls will go to either of these classes.
39
if ($is_windows) {
40
  require Proc::Background::Win32;
41
  unshift(@Proc::Background::ISA, 'Proc::Background::Win32');
42
} else {
43
  require Proc::Background::Unix;
44
  unshift(@Proc::Background::ISA, 'Proc::Background::Unix');
45
}
46
 
47
# Take either a relative or absolute path to a command and make it an
48
# absolute path.
49
sub _resolve_path {
50
  my $command = shift;
51
 
52
  return ( undef, 'empty command string' ) unless length $command;
53
 
54
  # Make the path to the progam absolute if it isn't already.  If the
55
  # path is not absolute and if the path contains a directory element
56
  # separator, then only prepend the current working to it.  If the
57
  # path is not absolute, then look through the PATH environment to
58
  # find the executable.  In all cases, look for the programs with any
59
  # extensions added to the original path name.
60
  my $path;
61
  if ($command =~ /$is_absolute_re/o) {
62
    foreach my $ext (@extensions) {
63
      my $p = "$command$ext";
64
      if (-f $p and -x _) {
65
        $path = $p;
66
        last;
67
      }
68
    }
69
    return defined $path? ( $path, undef ) : ( undef, "no executable program located at $command" );
70
  } else {
71
    my $cwd = cwd;
72
    if ($command =~ /$has_dir_element_re/o) {
73
      my $p1 = "$cwd$path_sep$command";
74
      foreach my $ext (@extensions) {
75
        my $p2 = "$p1$ext";
76
        if (-f $p2 and -x _) {
77
          $path = $p2;
78
          last;
79
        }
80
      }
81
    } else {
82
      foreach my $dir (split($is_windows ? ';' : ':', $ENV{PATH})) {
83
        next unless length $dir;
84
        $dir = "$cwd$path_sep$dir" unless $dir =~ /$is_absolute_re/o;
85
        my $p1 = "$dir$path_sep$command";
86
        foreach my $ext (@extensions) {
87
          my $p2 = "$p1$ext";
88
          if (-f $p2 and -x _) {
89
            $path = $p2;
90
            last;
91
          }
92
        }
93
        last if defined $path;
94
      }
95
    }
96
    return defined $path? ( $path, undef ) : ( undef, "cannot find absolute location of $command" );
97
  }
98
}
99
 
100
# Define the set of allowed options, to warn about unknown ones.
101
# Make it a method so subclasses can override it.
102
%Proc::Background::_available_options= (
103
  autodie => 1, command => 1, exe => 1,
104
  cwd => 1, stdin => 1, stdout => 1, stderr => 1,
105
  autoterminate => 1, die_upon_destroy => 1,
106
);
107
 
108
sub _available_options {
109
  return \%Proc::Background::_available_options;
110
}
111
 
112
# We want the created object to live in Proc::Background instead of
113
# the OS specific class so that generic method calls can be used.
114
sub new {
115
  my $class = shift;
116
 
117
  # The parameters are an optional %options hashref followed by any number
118
  # of arguments to become the @argv for exec().  If options are given, check
119
  # the keys for typos.
120
  my $options;
121
  if (@_ and ref $_[0] eq 'HASH') {
122
    $options= shift;
123
    my $known= $class->_available_options;
124
    my @unknown= grep !$known->{$_}, keys %$options;
125
    carp "Unknown options: ".join(', ', @unknown)
126
      if @unknown;
127
  }
128
  else {
129
    $options= {};
130
  }
131
 
132
  my $self= bless {}, $class;
133
  $self->{_autodie}= 1 if $options->{autodie};
134
 
135
  # Resolve any confusion between the 'command' option and positional @argv params.
136
  # Store the command in $self->{_command} so that the ::Unix and ::Win32 don't have
137
  # to deal with it redundantly.
138
  my $cmd= $options->{command};
139
  if (defined $cmd) {
140
    croak "Can't use both 'command' option and command argument list"
141
      if @_;
142
    # Can be an arrayref or a single string
143
    croak "command must be a non-empty string or an arrayref of strings"
144
      unless (ref $cmd eq 'ARRAY' && defined $cmd->[0] && length $cmd->[0])
145
        or (!ref $cmd && defined $cmd && length $cmd);
146
  }
147
  else {
148
    # Back-compat: maintain original API quirks
149
    confess "Proc::Background::new called with insufficient number of arguments"
150
      unless @_;
151
    return $self->_fatal('command is undefined') unless defined $_[0];
152
 
153
    # Interpret the parameters as an @argv if there is more than one,
154
    # or if the 'exe' option was given.
155
    $cmd= (@_ > 1 || defined $options->{exe})? [ @_ ] : $_[0];
156
  }
157
 
158
  $self->{_command}= $cmd;
159
  $self->{_exe}= $options->{exe} if defined $options->{exe};
160
 
161
  # Also back-compat: failing to fork or CreateProcess returns undef
162
  return unless $self->_start($options);
163
 
164
  # Save the start time
165
  $self->{_start_time} = time;
166
 
167
  if ($options->{autoterminate} || $options->{die_upon_destroy}) {
168
    $self->autoterminate(1);
169
  }
170
 
171
  return $self;
172
}
173
 
174
# The original API returns undef from the constructor in case of various errors.
175
# The autodie option converts these undefs into exceptions.
176
sub _fatal {
177
  my ($self, $message)= @_;
178
  croak $message if $self->{_autodie};
179
  warn "$0: $message";
180
  return undef;
181
}
182
 
183
sub autoterminate {
184
  my ($self, $newval)= @_;
185
  if (@_ > 1 and ($newval xor $self->{_die_upon_destroy})) {
186
    if ($newval) {
187
      # Global destruction can break this feature, because there are no guarantees
188
      # on which order object destructors are called.  In order to avoid that, need
189
      # to run all the ->die methods during END{}, and that requires weak
190
      # references which weren't available until 5.8
191
      $weaken_subref->( $Proc::Background::_die_upon_destroy{$self+0}= $self )
192
        if $weaken_subref;
193
      # could warn about it for earlier perl... but has been broken for 15 years and
194
      # who is still using < 5.8 anyway?
195
    }
196
    else {
197
      delete $Proc::Background::_die_upon_destroy{$self+0};
198
    }
199
    $self->{_die_upon_destroy}= $newval? 1 : 0;
200
  }
201
  $self->{_die_upon_destroy} || 0
202
}
203
 
204
sub DESTROY {
205
  my $self = shift;
206
  if ($self->{_die_upon_destroy}) {
207
    # During a mainline exit() $? is the prospective exit code from the
208
    # parent program. Preserve it across any waitpid() in die()
209
    local $?;
210
    $self->terminate;
211
    delete $Proc::Background::_die_upon_destroy{$self+0};
212
  }
213
}
214
 
215
END {
216
  # Child processes need killed before global destruction, else the
217
  # Win32::Process objects might get destroyed first.
218
  for (grep defined, values %Proc::Background::_die_upon_destroy) {
219
    $_->terminate;
220
    delete $_->{_die_upon_destroy}
221
  }
222
  %Proc::Background::_die_upon_destroy= ();
223
}
224
 
225
# Reap the child.  If the first argument is false, then return immediately.
226
# Else, block waiting for the process to exit.  If no second argument is
227
# given, wait forever, else wait for that number of seconds.
228
# If the wait was sucessful, then delete
229
# $self->{_os_obj} and set $self->{_exit_value} to the OS specific
230
# class return of _reap.  Return 1 if we sucessfully waited, 0
231
# otherwise.
232
sub _reap {
233
  my ($self, $blocking, $wait_seconds) = @_;
234
 
235
  return 0 unless exists($self->{_os_obj});
236
 
237
  # Try to wait on the process.  Use the OS dependent wait call using
238
  # the Proc::Background::*::waitpid call, which returns one of three
239
  # values.
240
  #   (0, exit_value)   : sucessfully waited on.
241
  #   (1, undef)        : process already reaped and exit value lost.
242
  #   (2, undef)        : process still running.
243
  my ($result, $exit_value) = $self->_waitpid($blocking, $wait_seconds);
244
  if ($result == 0 or $result == 1) {
245
    $self->{_exit_value} = defined($exit_value) ? $exit_value : 0;
246
    delete $self->{_os_obj};
247
    # Save the end time of the class.
248
    $self->{_end_time} = time;
249
    return 1;
250
  }
251
  return 0;
252
}
253
 
254
sub alive {
255
  my $self = shift;
256
 
257
  # If $self->{_os_obj} is not set, then the process is definitely
258
  # not running.
259
  return 0 unless exists($self->{_os_obj});
260
 
261
  # If $self->{_exit_value} is set, then the process has already finished.
262
  return 0 if exists($self->{_exit_value});
263
 
264
  # Try to reap the child.  If it doesn't reap, then it's alive.
265
  !$self->_reap(0);
266
}
267
 
268
sub suspended {
269
  $_[0]->{_suspended}? 1 : 0
270
}
271
 
272
sub suspend {
273
  my $self= shift;
274
  return $self->_fatal("can't suspend, process has exited")
275
    if !$self->{_os_obj};
276
  $self->{_suspended} = 1 if $self->_suspend;
277
  return $self->{_suspended};
278
}
279
 
280
sub resume {
281
  my $self= shift;
282
  return $self->_fatal("can't resume, process has exited")
283
    if !$self->{_os_obj};
284
  $self->{_suspended} = 0 if $self->_resume;
285
  return !$self->{_suspended};
286
}
287
 
288
sub wait {
289
  my ($self, $timeout_seconds) = @_;
290
 
291
  # If $self->{_exit_value} exists, then we already waited.
292
  return $self->{_exit_value} if exists($self->{_exit_value});
293
 
294
  carp "calling ->wait on a suspended process" if $self->{_suspended};
295
 
296
  # If neither _os_obj or _exit_value are set, then something is wrong.
297
  return undef if !exists($self->{_os_obj});
298
 
299
  # Otherwise, wait for the process to finish.
300
  return $self->_reap(1, $timeout_seconds)? $self->{_exit_value} : undef;
301
}
302
 
303
sub terminate { shift->die(@_) }
304
sub die {
305
  my $self = shift;
306
 
307
  croak "process is already terminated" if $self->{_autodie} && !$self->{_os_obj};
308
 
309
  # See if the process has already died.
310
  return 1 unless $self->alive;
311
 
312
  # Kill the process using the OS specific method.
313
  $self->_terminate(@_? ([ @_ ]) : ());
314
 
315
  # See if the process is still alive.
316
  !$self->alive;
317
}
318
 
319
sub command {
320
  $_[0]->{_command};
321
}
322
 
323
sub exe {
324
  $_[0]->{_exe}
325
}
326
 
327
sub start_time {
328
  $_[0]->{_start_time};
329
}
330
 
331
sub exit_code {
332
  return undef unless exists $_[0]->{_exit_value};
333
  return $_[0]->{_exit_value} >> 8;
334
}
335
 
336
sub exit_signal {
337
  return undef unless exists $_[0]->{_exit_value};
338
  return $_[0]->{_exit_value} & 127;
339
}
340
 
341
sub end_time {
342
  $_[0]->{_end_time};
343
}
344
 
345
sub pid {
346
  $_[0]->{_pid};
347
}
348
 
349
sub timeout_system {
350
  unless (@_ > 1) {
351
    confess "$0: timeout_system passed too few arguments.\n";
352
  }
353
 
354
  my $timeout = shift;
355
  unless ($timeout =~ /^\d+(?:\.\d*)?$/ or $timeout =~ /^\.\d+$/) {
356
    confess "$0: timeout_system passed a non-positive number first argument.\n";
357
  }
358
 
359
  my $proc = Proc::Background->new(@_) or return;
360
  my $end_time = $proc->start_time + $timeout;
361
  my $delay= $timeout;
362
  while ($delay > 0 && defined $proc->{_os_obj}) {
363
    last if defined $proc->wait($delay);
364
    # If it times out, it's likely that wait() already waited the entire duration.
365
    # But, if it got interrupted, there might be time remaining.
366
    # But, if the system clock changes, this could break horribly.  Constrain it to a sane value.
367
    my $t= time;
368
    if ($t < $end_time - $delay) { # time moved backward!
369
      $end_time= $t + $delay;
370
    } else {
371
      $delay= $end_time - $t;
372
    }
373
  }
374
 
375
  my $alive = $proc->alive;
376
  $proc->terminate if $alive;
377
 
378
  if (wantarray) {
379
    return ($proc->wait, $alive);
380
  } else {
381
    return $proc->wait;
382
  }
383
}
384
 
385
1;
386
 
387
__END__
388
 
389
=pod
390
 
391
=encoding UTF-8
392
 
393
=head1 NAME
394
 
395
Proc::Background - Generic interface to Unix and Win32 background process management
396
 
397
=head1 SYNOPSIS
398
 
399
  use Proc::Background;
400
  timeout_system($seconds, $command, $arg1, $arg2);
401
  timeout_system($seconds, "$command $arg1 $arg2");
402
 
403
  my $proc1 = Proc::Background->new($command, $arg1, $arg2) || die "failed";
404
  my $proc2 = Proc::Background->new("$command $arg1 1>&2") || die "failed";
405
  if ($proc1->alive) {
406
    $proc1->terminate;
407
    $proc1->wait;
408
  }
409
  say 'Ran for ' . ($proc1->end_time - $proc1->start_time) . ' seconds';
410
 
411
  Proc::Background->new({
412
    autodie => 1,           # Throw exceptions instead of returning undef
413
    cwd => 'some/path/',    # Set working directory for the new process
414
    exe => 'busybox',       # Specify executable different from argv[0]
415
    command => [ $command ] # resolve ambiguity of command line vs. argv[0]
416
  });
417
 
418
  # Set initial file handles
419
  Proc::Background->new({
420
    stdin => undef,                # /dev/null or NUL
421
    stdout => '/append/to/fname',  # will try to open()
422
    stderr => $log_fh,             # use existing handle
423
    command => \@command,
424
  });
425
 
426
  # Automatically kill the process if the object gets destroyed
427
  my $proc4 = Proc::Background->new({ autoterminate => 1 }, $command);
428
  $proc4    = undef;  # calls ->terminate
429
 
430
=head1 DESCRIPTION
431
 
432
This is a generic interface for placing processes in the background on
433
both Unix and Win32 platforms.  This module lets you start, kill, wait
434
on, retrieve exit values, and see if background processes still exist.
435
 
436
=head1 CONSTRUCTOR
437
 
438
=over 4
439
 
440
=item B<new> [options] I<command>, [I<arg>, [I<arg>, ...]]
441
 
442
=item B<new> [options] 'I<command> [I<arg> [I<arg> ...]]'
443
 
444
This creates a new background process.  Just like C<system()>, you can
445
supply a single string of the entire command line, or individual
446
arguments.  The first argument may be a hashref of named options.
447
To resolve the ambiguity between a command line vs. a single-element
448
argument list, see the C<command> option below.
449
 
450
By default, the constructor returns an empty list on failure,
451
except for a few cases of invalid arguments which call C<croak>.
452
 
453
For platform-specific details, see L<Proc::Background::Unix/IMPLEMENTATION>
454
or L<Proc::Background::Win32/IMPLEMENTATION>, but in short:
455
 
456
=over 7
457
 
458
=item Unix
459
 
460
This implementation uses C<fork>/C<exec>.  If you supply a single-string
461
command line, it is passed to the shell.  If you supply multiple arguments,
462
they are passed to C<exec>.  In the multi-argument case, it will also check
463
that the executable exists before calling C<fork>.
464
 
465
=item Win32
466
 
467
This implementation uses the L<Windows CreateProcess API|Win32::Process/METHODS>.
468
If you supply a single-string command line, it derives the executable by
469
parsing the command line and looking for the first element in the C<PATH>,
470
appending C<".exe"> if needed.  If you supply multiple arguments, the
471
first is used as the C<exe> and the command line is built using
472
L<Win32::ShellQuote>.
473
 
474
=back
475
 
476
B<Options:>
477
 
478
=over
479
 
480
=item C<autodie>
481
 
482
This module traditionally has returned C<undef> if the child could not
483
be started.  Modern Perl recommends the use of exceptions for things
484
like this.  This option, like Perl's L<autodie> pragma, causes all
485
fatal errors in starting the process to die with exceptions instead of
486
returning undef.
487
 
488
=item C<command>
489
 
490
You may specify the command as an option instead of passing the command
491
as a list.  A string value is considered a command line, and an arrayref
492
value is considered an argument list.  This can resolve the ambiguity
493
between a command line vs. single-element argument list.
494
 
495
=item C<exe>
496
 
497
Specify the executable.  This can serve two purposes:
498
on Win32 it avoids the parsing of the commandline, and on Unix it can be
499
used to run an executable while passing a different value for C<$ARGV[0]>.
500
 
501
=item C<stdin>, C<stdout>, C<stderr>
502
 
503
Specify one or more overrides for the standard handles of the child.
504
The value should be a Perl filehandle with an underlying system C<fileno>
505
value.  As a convenience, you can pass C<undef> to open the C<NUL> device
506
on Win32 or C</dev/null> on Unix.  You may also pass a plain-scalar file
507
name which this module will attmept to open for reading or appending.
508
 
509
(for anything more elaborate, see L<IPC::Run> instead)
510
 
511
Note that on Win32, none of the parent's handles are inherited by default,
512
which is the opposite on Unix.  When you specify any of these handles on
513
Win32 the default will change to inherit them from the parent.
514
 
515
=item C<cwd>
516
 
517
Specify a path which should become the child process's current working
518
directory.  The path must already exist.
519
 
520
=item C<autoterminate>
521
 
522
If you pass a true value for this option, then destruction of the
523
Proc::Background object (going out of scope, or script-end) will kill the
524
process via C<< ->terminate >>.  Without this option, the child process
525
continues running.  C<die_upon_destroy> is an alias for this option, used
526
by previous versions of this module.
527
 
528
=back
529
 
530
=back
531
 
532
=head1 ATTRIBUTES
533
 
534
=over
535
 
536
=item B<command>
537
 
538
The command (string or arrayref) that was passed to the constructor.
539
 
540
=item B<exe>
541
 
542
The path to the executable that was passed as an option to the constructor,
543
or derived from the C<command>.
544
 
545
=item B<start_time>
546
 
547
Return the value that the Perl function time() returned when the
548
process was started.
549
 
550
=item B<pid>
551
 
552
Returns the process ID of the created process.  This value is saved
553
even if the process has already finished.
554
 
555
=item B<alive>
556
 
557
Return 1 if the process is still active, 0 otherwise.  This makes a
558
non-blocking call to C<wait> to check the real status of the process if it
559
has not been reaped yet.
560
 
561
=item B<suspended>
562
 
563
Boolean whether the process is thought to be stopped.  This does not actually
564
consult the operating system, and just returns the last known status from a
565
call to C<suspend> or C<resume>.  It is always false if C<alive> is false.
566
 
567
=item B<exit_code>
568
 
569
Returns the exit code of the process, assuming it exited cleanly.
570
Returns C<undef> if the process has not exited yet, and 0 if the
571
process exited with a signal (or TerminateProcess).  Since 0 is
572
ambiguous, check for C<exit_signal> first.
573
 
574
=item B<exit_signal>
575
 
576
Returns the value of the signal the process exited with, assuming it
577
died on a signal.  Returns C<undef> if it has not exited yet, and 0
578
if it did not die to a signal.
579
 
580
=item B<end_time>
581
 
582
Return the value that the Perl function time() returned when the exit
583
status was obtained from the process.
584
 
585
=item B<autoterminate>
586
 
587
This writeable attribute lets you enable or disable the autoterminate
588
option, which could also be passed to the constructor.
589
 
590
=back
591
 
592
=head1 METHODS
593
 
594
=over
595
 
596
=item B<wait>
597
 
598
  $exit= $proc->wait; # blocks forever
599
  $exit= $proc->wait($timeout_seconds); # since version 1.20
600
 
601
Wait for the process to exit.  Return the exit status of the command
602
as returned by wait() on the system.  To get the actual exit value,
603
divide by 256 or right bit shift by 8, regardless of the operating
604
system being used.  If the process never existed, this returns undef.
605
This function may be called multiple times even after the process has
606
exited and it will return the same exit status.
607
 
608
Since version 1.20, you may pass an optional argument of the number of
609
seconds to wait for the process to exit.  This may be fractional, and
610
if it is zero then the wait will be non-blocking.  Note that on Unix
611
this is implemented with L<Time::HiRes/alarm> before a call to wait(),
612
so it may not be compatible with scripts that use alarm() for other
613
purposes, or systems/perls that resume system calls after a signal.
614
In the event of a timeout, the return will be undef.
615
 
616
=item B<suspend>
617
 
618
Pause the process.  This returns true if the process is stopped afterward.
619
This throws an excetion if the process is not C<alive> and C<autodie> is
620
enabled.
621
 
622
=item B<resume>
623
 
624
Resume a paused process.  This returns true if the process is not stopped
625
afterward.  This throws an exception if the process is not C<alive> and
626
C<autodie> is enabled.
627
 
628
=item B<terminate>, B<terminate(@kill_sequence)>
629
 
630
Reliably try to kill the process.  Returns 1 if the process no longer
631
exists once B<terminate> has completed, 0 otherwise.  This will also return
632
1 if the process has already exited.
633
 
634
C<@kill_sequence> is a list of actions and seconds-to-wait for that
635
action to end the process.  The default is C< TERM 2 TERM 8 KILL 3 KILL 7 >.
636
On Unix this sends SIGTERM and SIGKILL; on Windows it just calls
637
TerminateProcess (graceful terminationthe second is set to 1 if the process was killed by
638
B<timeout_system> or 0 if the process exited by itself.
639
 
640
The exit status is the value returned from the wait() call.  If the
641
process was killed, then the return value will include the killing of
642
it.  To get the actual exit value, divide by 256.
643
 
644
If something failed in the creation of the process, the subroutine
645
returns an empty list in a list context, an undefined value in a
646
scalar context, or nothing in a void context.
647
 
648
=back
649
 
650
=head1 SEE ALSO
651
 
652
=over
653
 
654
=item L<IPC::Run>
655
 
656
IPC::Run is a much more complete solution for running child processes.
657
It handles dozens of forms of redirection and pipe pumping, and should
658
probably be your first stop for any complex needs.
659
 
660
However, also note the very large and slightly alarming list of
661
limitations it lists for Win32.  Proc::Background is a much simpler design
662
and should be more reliable for simple needs.
663
 
664
=item L<Win32::ShellQuote>
665
 
666
If you are running on Win32, this article by Daniel Colascione helps
667
describe the problem you are up against for passing argument lists:
668
L<Everyone quotes command line arguments the wrong way|https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/>
669
 
670
This module gives you parsing / quoting per the standard
671
CommandLineToArgvW behavior.  But, if you need to pass arguments to be
672
processed by C<cmd.exe> then you need to do additional work.
673
 
674
=back
675
 
676
=head1 AUTHORS
677
 
678
=over 4
679
 
680
=item *
681
 
682
Blair Zajac <blair@orcaware.com>
683
 
684
=item *
685
 
686
Michael Conrad <mike@nrdvana.net>
687
 
688
=back
689
 
690
=head1 CONTRIBUTORS
691
 
692
=for stopwords Florian Schlichting Kevin Ryde Salvador Fandiño
693
 
694
=over 4
695
 
696
=item *
697
 
698
Florian Schlichting <fsfs@debian.org>
699
 
700
=item *
701
 
702
Kevin Ryde <user42@zip.com.au>
703
 
704
=item *
705
 
706
Salvador Fandiño <sfandino@yahoo.com>
707
 
708
=back
709
 
710
=head1 VERSION
711
 
712
version 1.30
713
 
714
=head1 COPYRIGHT AND LICENSE
715
 
716
This software is copyright (c) 2021 by Michael Conrad, (C) 1998-2009 by Blair Zajac.
717
 
718
This is free software; you can redistribute it and/or modify it under
719
the same terms as the Perl 5 programming language system itself.
720
 
721
=cut

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.