File Coverage

blib/lib/Net/Goofey.pm
Criterion Covered Total %
statement 80 137 58.3
branch 5 28 17.8
condition 5 16 31.2
subroutine 16 29 55.1
pod 1 21 4.7
total 107 231 46.3


line stmt bran cond sub pod time code
1             package Net::Goofey;
2             #
3             # Perl interface to the Goofey server.
4             #
5             # ObLegalStuff:
6             # Copyright (c) 1998 Bek Oberin. All rights reserved. This program is
7             # free software; you can redistribute it and/or modify it under the
8             # same terms as Perl itself.
9             #
10             # Last updated by gossamer on Mon May 17 15:21:57 EST 1999
11             #
12              
13 1     1   203680 use strict;
  1         3  
  1         44  
14 1     1   5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %Messages);
  1         2  
  1         92  
15              
16             require Exporter;
17              
18 1     1   722 use IO::Socket;
  1         24133  
  1         6  
19 1     1   1216 use Sys::Hostname;
  1         995  
  1         41  
20 1     1   5 use Symbol;
  1         1  
  1         44  
21 1     1   4 use Fcntl;
  1         1  
  1         307  
22 1     1   5 use Carp;
  1         1  
  1         1715  
23              
24             @ISA = qw(Exporter);
25             @EXPORT = qw( %Messages );
26             @EXPORT_OK = qw();
27             $VERSION = "1.4";
28              
29              
30             =head1 NAME
31              
32             Net::Goofey - Communicate with a Goofey server
33              
34             =head1 SYNOPSIS
35              
36             use Net::Goofey;
37            
38             $Goofey = Net::Goofey->new();
39             $Goofey->signon();
40              
41             =head1 DESCRIPTION
42              
43             C is a class implementing a simple Goofey client in
44             Perl.
45              
46             =cut
47              
48             ###################################################################
49             # Some constants #
50             ###################################################################
51              
52             # Messages returned by server
53             %Messages = (
54             "exit" => "E",
55             "idle" => "W",
56             "message" => "Z",
57             );
58              
59             my $Default_Goofey_Port = 3987;
60             my $Default_Goofey_Host = "pluto.cc.monash.edu.au";
61              
62             my $Client_Type = "G";
63             my $Client_Version = "3.51"; # Version of the base client we are imitating
64              
65             my $Password_File = $ENV{"HOME"} . "/.goofeypw";
66              
67             my $DEBUG = 0;
68              
69             ###################################################################
70             # Functions under here are member functions #
71             ###################################################################
72              
73             =head1 CONSTRUCTOR
74              
75             =item new ( [ USERNAME [, PASSWORD [, HOST [, PORT ] ] ] ])
76              
77             This is the constructor for a new Goofey object.
78              
79             C defaults, in order, to the environment variables
80             C, C then C.
81              
82             C defaults to the contents of the file C<$HOME/.goofeypw>.
83              
84             C and C refer to the remote host to which a Goofey
85             connection is required.
86              
87             The constructor returns the open socket, or C if an error has
88             been encountered.
89              
90             =cut
91              
92             sub new {
93 2     2 1 1913 my $prototype = shift;
94 2         11 my $username = shift;
95 2         8 my $password = shift;
96 2         4 my $host = shift;
97 2         4 my $port = shift;
98              
99 2   33     24 my $class = ref($prototype) || $prototype;
100 2         5 my $self = {};
101              
102 2 50       7 warn "new\n" if $DEBUG > 1;
103              
104 2   50     60 $self->{"username"} = $username || $ENV{"GOOFEYUSER"} || $ENV{"USER"} || $ENV{"LOGNAME"} || "unknown";
105 2   33     22 $self->{"password"} = $password || &find_password;
106 2   33     24 $self->{"host"} = $host || $Default_Goofey_Host;
107 2   33     17 $self->{"port"} = $port || $Default_Goofey_Port;
108 2         6 $self->{"incoming_port"} = 0; # It gets set later if it's needed
109 2         7 $self->{"extended_options"} = ""; # Not yet implemented
110 2         10332 my $tty = `tty`;
111 2         57 $self->{"tty"} = chomp($tty);
112              
113             # open the connection
114 2         162 $self->{"socket"} = new IO::Socket::INET (
115             Proto => "tcp",
116             PeerAddr => $self->{"host"},
117             PeerPort => $self->{"port"},
118             );
119 2 50       932481 croak "new: connect socket: $!" unless $self->{"socket"};
120              
121 2         48 bless($self, $class);
122 2         95 return $self;
123             }
124              
125              
126             #
127             # destructor
128             #
129             sub DESTROY {
130 2     2   126 my $self = shift;
131              
132 2         36 shutdown($self->{"socket"}, 2);
133 2         97 close($self->{"socket"});
134              
135 2         59313 return 1;
136             }
137              
138              
139             =head1 FUNCTIONS
140             =item signon ( );
141              
142             Register this client as the resident one.
143              
144             =cut
145              
146             sub signon {
147 0     0 0 0 my $self = shift;
148              
149 0   0     0 $self->{"incoming_port"} = &find_incoming_port() ||
150             die "Can't find an incoming port\n";
151              
152             # Empty command - register us as the main client
153 0         0 return $self->send_message($self->build_message(""));
154              
155             }
156              
157             =pod
158             =item send ( USERNAME, MESSAGE );
159              
160             Send a message to a goofey user
161             (Will clients handle their own iteration for multi-user messages, or
162             should we? For now I'm assuming that they will do it.)
163              
164             =cut
165              
166             sub send {
167 1     1 0 96541 my $self = shift;
168 1         23 my $username = shift;
169 1         12 my $message = shift;
170              
171 1         62 return $self->do_message("s $username $message");
172             }
173              
174             =pod
175             =item unsend ( USERNAME );
176              
177             Delete your last message to USERNAME, provided (of course) they
178             haven't read it.
179              
180             =cut
181              
182             sub unsend {
183 0     0 0 0 my $self = shift;
184 0         0 my $username = shift;
185 0         0 my $message = shift;
186              
187 0         0 return $self->do_message("s! $username");
188             }
189              
190             =pod
191             =item register ([COMMAND]);
192              
193             Register for goofey.
194              
195             Valid commands:
196             create Register new user
197             sendpw Request your existing password be emailed to you
198             alias Register this machine as an alias
199             request Request another goofey name to alias current one
200              
201             =cut
202              
203             sub register {
204 0     0 0 0 my $self = shift;
205 0         0 my $argument = shift;
206              
207 0         0 return $self->do_message("N $argument");
208             }
209              
210             =pod
211             =item who ([USERNAME]);
212              
213             List that user's finger information.
214              
215             =cut
216              
217             sub who {
218 1     1 0 83 my $self = shift;
219 1         13 my $username = shift;
220              
221 1         28 return $self->do_message("w $username");
222             }
223              
224             =pod
225             =item list ([USERNAME]);
226              
227             List the locations and idle times of user. If user is empty then all
228             users are listed, but their idle times are not queried: the last
229             obtained idle time is printed. Users those idle times are more than 1
230             hour are not listed.
231             =cut
232              
233             sub list {
234 0     0 0 0 my $self = shift;
235 0         0 my $username = shift;
236            
237 0         0 return $self->do_message("l $username");
238             }
239              
240             =pod
241             =item quiet ();
242              
243             Sets you quiet. The server will then keep your messages until you
244             unquiet. This mode lets through messages from anybody on your unquiet
245             alias, though.
246              
247             =cut
248              
249             sub quiet {
250 0     0 0 0 my $self = shift;
251 0         0 my $quietmsg = shift;
252            
253 0         0 return $self->do_message("Q- $quietmsg");
254             }
255              
256             =pod
257             =item quietall ();
258              
259             Sets you quiet to everybody.
260              
261             =cut
262              
263             sub quietall {
264 0     0 0 0 my $self = shift;
265 0         0 my $quietmsg = shift;
266            
267 0         0 return $self->do_message("Q! $quietmsg");
268             }
269              
270             =pod
271             =item repeat ();
272              
273             Repeats certain messages
274              
275             =cut
276              
277             sub repeat {
278 0     0 0 0 my $self = shift;
279 0         0 my $which = shift;
280            
281 0         0 return $self->do_message("r $which");
282             }
283              
284             =pod
285             =item unquiet ();
286              
287             Sets you unquiet.
288              
289             =cut
290              
291             sub unquiet {
292 0     0 0 0 my $self = shift;
293            
294 0         0 return $self->do_message("Q+");
295             }
296              
297             =pod
298             =item killclient ();
299              
300             Sets you unquiet.
301              
302             =cut
303              
304             sub killclient {
305 0     0 0 0 my $self = shift;
306 0         0 my $which = shift;
307 0         0 my $killmsg = shift;
308            
309 0 0       0 $which = "" if $which eq "this";
310 0 0       0 $killmsg = "- " . $killmsg if $killmsg;
311 0         0 return $self->do_message("x $which $killmsg");
312             }
313              
314             =pod
315             =item listen ( );
316              
317             Listens for a command from the Goofey server. If we don't already
318             have an open port to them, opens it.
319              
320             =cut
321              
322             sub listen {
323 0     0 0 0 my $self = shift;
324              
325 0         0 my ($message_type, $message_text, $message);
326              
327 0 0       0 if (!$self->{"incoming_socket"}) {
328             # open the connection
329 0         0 $self->{"incoming_socket"} = new IO::Socket::INET (
330             Proto => "tcp",
331             LocalPort => $self->{"incoming_port"},
332             Listen => 1,
333             Reuse => 1,
334             );
335 0 0       0 croak "incoming socket: $!" unless $self->{"incoming_socket"};
336             }
337              
338             # listening ...
339 0         0 my $client = $self->{"incoming_socket"}->accept();
340              
341 0         0 while (<$client>) {
342 0         0 $message .= $_;
343             }
344              
345             #($message_type, $message_text) = ($message =~ /^(.)(.*)$/);
346 0         0 $message_type = substr($message,0,1);
347 0         0 substr($message,0,1) = ""; $message_text = $message;
  0         0  
348 0 0       0 warn "Message Type: '$message_type'\n" if $DEBUG;
349 0 0       0 warn "Message: '$message_text'\n" if $DEBUG;
350              
351 0 0       0 if ($message_type eq $Messages{"message"}) {
352             # trim off random weirdness
353             # **** A message has arrived from pluto on Mon May 17 11:29! ****
354             #$message_text =~ s/^\s*\*\*\*\* A message has arrived from (\S+) on ([^!]+)\! \*\*\*\*\s*//s;
355 0         0 $message_text =~ s/^\s*\*\*\*\*.*\*\*\*\*\s*//s;
356              
357             }
358              
359 0 0       0 if ($message_type eq $Messages{"idle"}) {
360 0 0       0 warn "Returning idletime ..." if $DEBUG;
361 0         0 print $client &get_idletime();
362             }
363            
364 0         0 close $client;
365              
366 0         0 return $message_type, $message_text;
367              
368             }
369              
370             =pod
371             =item version ( );
372              
373             Returns version information.
374              
375             =cut
376              
377             sub version {
378 0     0 0 0 my $ver = "Net::Goofey version $VERSION, equivalent to goofey C client version $Client_Version";
379 0         0 return $ver;
380             }
381              
382              
383             ###################################################################
384             # Functions under here are helper functions #
385             ###################################################################
386              
387             #
388             # Does the whole build-send-getanswer thing
389             #
390             sub do_message {
391 2     2 0 16 my $self = shift;
392 2         8 my $command = shift;
393              
394 2         346 $self->send_message($self->build_message('*' . $command));
395 2         95 shutdown($self->{"socket"},1);
396              
397 2         12 return $self->get_answer();
398             }
399              
400             sub send_message {
401 2     2 0 20 my $self = shift;
402 2         8 my $message = shift;
403              
404 2 50       382 if (!defined(syswrite($self->{"socket"}, $message, length($message)))) {
405 0         0 warn "syswrite: $!";
406 0         0 return 0;
407             }
408              
409 2         8 return 1;
410            
411             }
412              
413             sub get_answer {
414 2     2 0 7 my $self = shift;
415              
416 2         17 my $buffer = "";
417 2         6 my $buff1;
418            
419 2         610822 while (sysread($self->{"socket"}, $buff1, 999999) > 0) {
420 2         76 $buffer .= $buff1;
421             }
422              
423 2         47 return $buffer;
424              
425             }
426              
427             sub build_message {
428 2     2 0 6 my $self = shift;
429 2         6 my $command = shift;
430              
431 2         142 my $message = "#" . $Client_Type . $Client_Version . "," .
432             $self->{"extended_options"} .
433             $self->{"username"} . "," .
434             $self->{"password"} . "," .
435             $self->{"incoming_port"} . "," .
436             $self->{"tty"};
437 2 50       3941 if ($command) {
438 2         129 $message .= "," . $command;
439             }
440            
441 2         6 $message .= "\n";
442              
443 2         18 return $message;
444             }
445              
446             # Reads password from the file
447             sub find_password {
448 2     2 0 10 my $password = "";
449              
450 2 50       159 open(PWD, $Password_File) ||
451             warn "Can't open password file '$Password_File': $!";
452 2         2961 $password = ;
453 2         1243 chomp($password);
454 2         1725 close(PWD);
455              
456 2         92 return $password;
457             }
458              
459             sub get_idletime {
460             # XXX fixme!
461              
462 0     0 0   return 0;
463             }
464              
465             # Searches for a port that the server can use to talk to us
466             sub find_incoming_port {
467 0     0 0   my $port = 9473;
468              
469 0           return $port;
470             }
471              
472             =pod
473              
474             =head1 AUTHOR
475              
476             Bek Oberin
477              
478             =head1 CREDITS
479              
480             Kirrily Robert
481              
482             =head1 COPYRIGHT
483              
484             Copyright (c) 1998 Bek Oberin. All rights reserved.
485              
486             This program is free software; you can redistribute it and/or modify
487             it under the same terms as Perl itself.
488              
489             =cut
490              
491             #
492             # End code.
493             #
494             1;