Perl Socket Problem

Posted on 1997-08-03
Last Modified: 2008-03-03
I want to be able to change my passwd on the server "ebs2.eecs" from my machine "ebs1.eecs" using sockets.
ebs2.eecs has an entry for the program under /etc/services and /etc/inetd.conf. On calling the program from ebs1.eecs I do get Testing.. as the output but nothing further happens.

1) What do I need to do to get this to work?
2) How come I don't get an output for $name when I call the
   client prog. with an output?

The client program that runs on my machine "ebs1.eecs"

# passwd.client

$AF_INET = 2;
$sockaddr = 'S n a4 x8';

chop ($user = `whoami`) unless $user;

$port = 1997;
$host = 'ebs2.eecs';

($n, $a, $proto) = getprotobyname('tcp');
($n, $a, $t, $l, @thisaddr) = gethostbyname('localhost');
($n, $a, $t, $l, @thataddr) = gethostbyname($host);

$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
$that = pack($sockaddr, $AF_INET, $port, @thataddr);

socket(S, $AF_INET, $SOCK_STREAM, $proto) || die "Can't open socket!\n";
bind(S, $this) || die "Couldn't bind a new socket!\n";
connect(S, $that) || die "Couldn't connect to host $host, port $port!\n";

select(S); $| = 1; select(STDOUT);

print S "$user\n";  ##Pass the user to the server                                  passwd.answerd prog

while (<S>) {

The server prog on "ebs2.eecs"

# passwd.server

$ENV{'PATH'} = '/bin:/etc:/etc/bin:/usr/bin:/usr/ucb:/usr/local/bin';
print "Testing.. \n" ;
local($name) = @_ ;

$AF_INET = 2;
$sockaddr = 'S n a4 x8';

$port = 1997;

($n, $a, $t, $l, @thisaddr) = gethostbyname($host);
($n, $a, $proto) = getprotobyname('tcp');
$thisport = pack($sockaddr,$AF_INET,$port,$thisaddr);
socket(S, $AF_INET, $SOCK_STREAM, $proto) || die "Can't open socket!";
bind(S,$thisport) || die "Cannot bind socket \n" ;
listen(S,5) || die "Cannot listen socket \n" ;
  accept(NS,S) || die "Cannot accept socket\n" ;
  system "/bin/passwd" ;
  close NS;

Question by:monish
  • 2

Accepted Solution

icculus earned 50 total points
ID: 1205181
The first thing I would recommend doing is changing the
socket handling techniques you are using to use the Socket
module provided with perl5.002 and higher.

# Sample code to get the server operating (assumes
# perl5.002 is installed at /usr/local/bin/perl):


require 5.002;
use Socket;
use Fcntl;
use POSIX;

$port = 1997;
$proto = getprotobyname('tcp');

# Open the socket, set socket options for reuse

socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die "setsockopt: $!";
setsockopt(Server, SOL_SOCKET, SO_LINGER, 0);

# bind socket, allowing 1 connection at a time, set
# non-blocking io

bind(Server, sockaddr_in($port, INADDR_ANY)) or die "bind: $!";
fcntl(Server, F_SETFL, O_NONBLOCK);
listen(Server, 1) or die "listen: $!";

for (; $paddr = accept(Client,Server); close Client){

   # Ok, the server has a connection which can now
   # be referenced as the filehandle Client.
   # Expect input in the form: user tab pwd
   # Warning: You will likely need to strip some
   # extra characters found at the end of the string.
   # You can do this by checking for non-null characters.

   my ($input) = <Client>;
   my ($user, $pwd) = (split("\t", $input));

   # You will likely need to reorganize the way you
   # interact wth the passwd command, see below.  
   # after executing pwd command the for loop closes
   # the connection.

# Sample Code for Interacting with passwd command

open(PWD, "|/bin/passwd $user");

   # You know what the password command prompts for
   # and you need to print to it in the order that
   # it requires.

   print PWD "${pwd}\n"; # Password to change to
   print PWD "${pwd}\n"; # Verification of new password

# Sample Client Code. Assumes same perl call and
# same same modules used

$remote  = "hostname.ext";
$port    = 1997
$iaddr   = inet_aton($remote) || return 0;
$paddr   = sockaddr_in($port, $iaddr);

# Open the scket
socket(SOCK, PF_INET, SOCK_STREAM, $proto);  
# Call up the server
connect(SOCK, $paddr);

   # Print the user name and password, tab-delim
   # The server should expect to read a string, tab, then
   # string.

   print "${user}\t${pwd}\n";

   # The server will close the connection when it is
   # done, this should end the while loop.

This should give you a basis for converting to the
Socket module, it is much better than using the old
socket handling techniques, which do not work on all
platforms. This example also shows you how to interact
with the password command through a named pipe. This is
also a good way of handling this...

Hope this helps!

Author Comment

ID: 1205182
I tried your example. I see the server process start up at
the server "ebs2" and get some error checking output on "ebs1".  
The following is the output I get back on ebs1 when I run the program :

bind: Address already in useCHECK C4

So it never goes pass the following line on the server :
bind(Server, $port)                     or die "bind: $!" ;

Any clues on how I can get the client and Server to talk and fix this ? Thanks.

The client code on ebs1 :

require 5.002;
use strict;
use Socket;
use Fcntl;
use POSIX;

my $user = `whoami` ;
my ($remote,$port,$iaddr,$paddr,$proto,$line);

$remote = "";
$port = 1995 ;

$iaddr = inet_aton($remote) or print "ERROR1\n" ;
$paddr = sockaddr_in($port, $iaddr);

# Open the socket
$proto = getprotobyname('tcp') ;
socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "Could'nt create socket";

# Call up the server
connect(SOCK, $paddr) or die "Couldn't connect socket";

print "CHECK C1\n" ;
##select(SOCK); $| = 1; select(STDOUT);
print "CHECK C2\n" ;

    print "CHECK C3\n" ;
    print ;
print "CHECK C4\n" ;
close (SOCK) || die "Couldn't close socket\n";
exit ;

The server code on ebs2 :

require 5.002;
use strict;
use Socket;
use Carp;
use Fcntl;
use POSIX;

print "CHECK S1\n" ;
my $port = 1995;
my $proto = getprotobyname('tcp');

socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!" ;
print "CHECK S2\n" ;
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("1",1))       or die "setsockopt: $!";
print "CHECK S3\n" ;
#bind(Server,sockaddr_in($port,INADDR_ANY)) or print "bind: $!" ;
bind(Server, $port)                     or die "bind: $!" ;
print "CHECK S4\n" ;
listen(Server,SOMAXCONN)                or die "listen: $!" ;

my $paddr;
for ( ; $paddr = accept(Client,Server); close Client)
  my($port, $iaddr) = sockaddr_in($paddr);
  my $name = gethostbyaddr($iaddr,AF_INET);
  print Client "Hello there, $name \n";



Expert Comment

ID: 1205183
Ok, the bind: Address already in use indicates that either
the port you are using is already bound by another program,
or it is bound by the current program but has not been.

For example, if you run the program and then kill it, the
port will remain bound for a few minutes. I have this problem
with a proxy server I use, it takes about 5 full minutes
before I can run it again after the server dies. Give it
some time and then try again. I know this sucks and is quite
a hassle when debugging but it happens... *sigh*


Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Extract multiple value with delimiters from a string 4 168
hard perl script 16 154
PERL - Find newest folder 12 118
Put query string from URL request -  PERL HTTP Daemon 2 73
Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (,  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now