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
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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

Want Experts Exchange at your fingertips?

With Experts Exchange’s latest app release, you can now experience our most recent features, updates, and the same community interface while on-the-go. Download our latest app release at the Android or Apple stores today!

Question has a verified solution.

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

I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (…
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…
Six Sigma Control Plans

626 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