Socket.pm: Fix detection and deletion of an existing socket file.
[people/stevee/guardian.git] / modules / Socket.pm
1 package Guardian::Socket;
2 use strict;
3 use warnings;
4
5 use Exporter qw(import);
6
7 our @EXPORT_OK = qw(Server Client Message_Parser);
8
9 use IO::Socket::UNIX qw( SOCK_STREAM SOMAXCONN );
10
11 # The path and filename to the UNIX socket.
12 my $socketpath = "/run/guardian";
13 my $socketfile = "/run/guardian/guardian.sock";
14
15 # Hash with all supported socket commands and events which should
16 # be returned by the parser.
17 my %supported_commands = (
18         'block' => 'block',
19         'unblock' => 'unblock',
20         'flush' => 'flush',
21         'reload' => 'reload',
22         'logrotate' => 'logrotate',
23 );
24
25 #
26 ## Socket server function.
27 #
28 ## It is used to create the server component to provide an IPC
29 ## mechanism for guardian.  The server function creates an UNIX
30 ## socket.
31 #
32 sub Server () {
33         # If the path for the socketfile does not exist, try to
34         # create it.
35         unless (-d "$socketpath") {
36                 mkdir("$socketpath") or die "Could not create $socketpath: $@\n";
37         }
38
39         # Delete an existing socket file.
40         if (-e "$socketfile") {
41                 unlink $socketfile
42                 or die "Could not release existing socket file: $!\n";
43         }
44
45         # Create a new UNIX socket.
46         my $server = IO::Socket::UNIX->new(
47                 Local => $socketfile,
48                 Listen => SOMAXCONN,
49                 Type => SOCK_STREAM,
50         ) or die "Could not create socket: $@\n";
51
52         # Return the server object.
53         return $server;
54 }
55
56 #
57 ## A client for the socket server.
58 #
59 ## This function provides a simple client to connect to the server socket
60 ## and send messages through it to a running guardian process.
61 #
62 sub Client($) {
63         my ($message) = @_;
64
65         # Create the client and connect to the server socket.
66         my $client = IO::Socket::UNIX->new(
67                 Type => SOCK_STREAM,
68                 Peer => $socketfile,
69         ) or die "Could not connect to socketfile: $!\n";
70
71         # Remove any newline.
72         chomp($message);
73
74         # Send the message through the socket.
75         print $client "$message\n";
76 }
77
78 #
79 ## The Socket message parser.
80 #
81 ## This subfunction is responsible for parsing any data or messages
82 ## which have been recieved through the server socket.
83 #
84 sub Message_Parser ($) {
85         # Splitt the message into single parts.
86         # The first part contains the command, the second
87         # one an optional argument.
88         my @message = split(/ /, $_[0]);
89         my ($command, $optarg, $unsupported) = @message;
90
91         # Currently only socket messages with two arguments (command and
92         # the additional argument which is required for some commands)
93         # are supported. If a third argument is passed, the message
94         # is invalid and the parser returns false.
95         if ($unsupported) {
96                 return undef;
97         }
98
99         # Check if we got a supported command.
100         if (exists $supported_commands{$command}) {
101                 # Check an optional argument has been given.
102                 if ($optarg) {
103                         # The message is valid, return the event and
104                         # the optional argument.
105                         return "$supported_commands{$command} $optarg";
106                 } else {
107                         # Only return the event for the recieved command.
108                         return "$supported_commands{$command}";
109                 }
110         }
111
112         # If we got here, the command was not supported or something different
113         # went wrong. In such cases the function will return undef (False).
114         return undef;
115 }
116
117 1;