summaryrefslogtreecommitdiff
path: root/lib/Net/DummyInetd.pm
blob: 8dddc901e64b7e2e88579fb89f8d997f2dd1b1cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# Net::DummyInetd.pm
#
# Copyright (c) 1995 Graham Barr <Graham.Barr@tiuk.ti.com>. All rights
# reserved. This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.

package Net::DummyInetd;

=head1 NAME

Net::DummyInetd - A dummy Inetd server

=head1 SYNOPSIS

    use Net::DummyInetd;
    use Net::SMTP;
    
    $inetd = new Net::DummyInetd qw(/usr/lib/sendmail -ba -bs);
    
    $smtp  = Net::SMTP->new('localhost', Port => $inetd->port);

=head1 DESCRIPTION

C<Net::DummyInetd> is just what it's name says, it is a dummy inetd server.
Creation of a C<Net::DummyInetd> will cause a child process to be spawned off
which will listen to a socket. When a connection arrives on this socket
the specified command is fork'd and exec'd with STDIN and STDOUT file
descriptors duplicated to the new socket.

This package was added as an example of how to use C<Net::SMTP> to connect
to a C<sendmail> process, which is not the default, via SIDIN and STDOUT.
A C<Net::Inetd> package will be avaliable in the next release of C<libnet>

=head1 CONSTRUCTOR

=over 4

=item new ( CMD )

Creates a new object and spawns a child process which listens to a socket.
C<CMD> is a list, which will be passed to C<exec> when a new process needs
to be created.

=back

=head1 METHODS

=over 4

=item port

Returns the port number on which the I<DummyInet> object is listening

=back

=head1 AUTHOR

Graham Barr <Graham.Barr@tiuk.ti.com>

=head1 REVISION

$Revision: 1.2 $

The VERSION is derived from the revision by changing each number after the
first dot into a 2 digit number so

	Revision 1.8   => VERSION 1.08
	Revision 1.2.3 => VERSION 1.0203

=head1 COPYRIGHT

Copyright (c) 1995 Graham Barr. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms
as Perl itself.

=cut

require 5.002;

use IO::Handle;
use IO::Socket;
use strict;
use vars qw($VERSION);
use Carp;

$VERSION = do{my @r=(q$Revision: 1.2 $=~/(\d+)/g);sprintf "%d."."%02d"x$#r,@r};


sub _process
{
 my $listen = shift;
 my @cmd = @_;
 my $vec = '';
 my $r;

 vec($vec,fileno($listen),1) = 1;

 while(select($r=$vec,undef,undef,undef))
  {
   my $sock = $listen->accept;
   my $pid;

   if($pid = fork())
    {
     sleep 1;
     close($sock);
    }
   elsif(defined $pid)
    {
     my $x =  IO::Handle->new_from_fd($sock,"r");
     open(STDIN,"<&=".fileno($x)) || die "$! $@";
     close($x);

     my $y = IO::Handle->new_from_fd($sock,"w");
     open(STDOUT,">&=".fileno($y)) || die "$! $@";
     close($y);

     close($sock);
     exec(@cmd) || carp "$! $@";
    }
   else
    {
     close($sock);
     carp $!;
    }
  }
 exit -1; 
}

sub new
{
 my $self = shift;
 my $type = ref($self) || $self;

 my $listen = IO::Socket::INET->new(Listen => 5, Proto => 'tcp');
 my $pid;

 return bless [ $listen->sockport, $pid ]
	if($pid = fork());

 _process($listen,@_);
}

sub port
{
 my $self = shift;
 $self->[0];
}

sub DESTROY
{
 my $self = shift;
 kill 9, $self->[1];
}

1;