~ubuntu-branches/ubuntu/hardy/freeradius/hardy-proposed

« back to all changes in this revision

Viewing changes to scripts/radsqlrelay

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2006-12-16 20:45:11 UTC
  • mfrom: (3.1.10 feisty)
  • Revision ID: james.westby@ubuntu.com-20061216204511-3pbbsu4s8jtehsor
Tags: 1.1.3-3
Fix POSIX compliance problem in init script.  Closes: #403384. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
##
 
3
##  radsqlrelay.pl      This program tails a SQL logfile and forwards
 
4
##                      the queries to a database server. Used to
 
5
##                      replicate accounting records to one (central)
 
6
##                      database, even if the database has extended
 
7
##                      downtime.
 
8
##
 
9
##  Version:    $Id: radsqlrelay,v 1.4.2.2 2006/08/17 12:20:41 nbk Exp $
 
10
##
 
11
##  Author:     Nicolas Baradakis <nicolas.baradakis@cegetel.net>
 
12
##
 
13
##  Copyright (C) 2005 Cegetel
 
14
##
 
15
##  This program is free software; you can redistribute it and/or
 
16
##  modify it under the terms of the GNU General Public License
 
17
##  as published by the Free Software Foundation; either version 2
 
18
##  of the License, or (at your option) any later version.
 
19
##
 
20
##  This program is distributed in the hope that it will be useful,
 
21
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
22
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
23
##  GNU General Public License for more details.
 
24
##
 
25
##  You should have received a copy of the GNU General Public License
 
26
##  along with this program; if not, write to the Free Software
 
27
##  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 
28
##
 
29
 
 
30
use DBI;
 
31
use Fcntl;
 
32
use Getopt::Std;
 
33
use POSIX qw(:unistd_h :errno_h);
 
34
 
 
35
use warnings;
 
36
use strict;
 
37
 
 
38
my $need_exit = 0;
 
39
 
 
40
sub got_signal()
 
41
{
 
42
    $need_exit = 1;
 
43
}
 
44
 
 
45
# /!\ OS-dependent structure
 
46
# Linux struct flock
 
47
#   short l_type;
 
48
#   short l_whence;
 
49
#   off_t l_start;
 
50
#   off_t l_len;
 
51
#   pid_t l_pid;
 
52
# c2ph says: typedef='s2 l2 i', sizeof=16
 
53
my $FLOCK_STRUCT = 's2l2i';
 
54
 
 
55
sub setlock($;$$)
 
56
{
 
57
    my ($fh, $start, $len) = @_;
 
58
    $start = 0 unless defined $start;
 
59
    $len = 0 unless defined $len;
 
60
 
 
61
                                    #type     whence    start   till  pid
 
62
    my $packed = pack($FLOCK_STRUCT, F_WRLCK, SEEK_SET, $start, $len, 0);
 
63
    if (fcntl($fh, F_SETLKW, $packed)) { return 1 }
 
64
    else { return 0 }
 
65
}
 
66
 
 
67
sub usage()
 
68
{
 
69
    print STDERR <<HERE;
 
70
usage: radsqlrelay [options] file_path
 
71
options:
 
72
        -?              Print this help message.
 
73
        -1              One-shot mode: push the file to database and exit.
 
74
        -b database     Name of the database to use.
 
75
        -d sql_driver   Driver to use: mysql, pg, oracle.
 
76
        -h host         Connect to host.
 
77
        -P port         Port number to use for connection.
 
78
        -p passord      Password to use when connecting to server.
 
79
        -u user         User for login.
 
80
        -x              Turn on debugging.
 
81
HERE
 
82
}
 
83
 
 
84
sub connect_wait($)
 
85
{
 
86
    my $dbinfo = shift;
 
87
    my $dbh;
 
88
    while (!$dbh) {
 
89
        $dbh = DBI->connect($dbinfo->{base}, $dbinfo->{user}, $dbinfo->{pass},
 
90
                            { RaiseError => 0, PrintError => 0,
 
91
                              AutoCommit => 1 });
 
92
        sleep (1) if !$dbh;
 
93
        exit if $need_exit;
 
94
    }
 
95
    $dbinfo->{handle} = $dbh;
 
96
}
 
97
 
 
98
sub process_file($$)
 
99
{
 
100
    my ($dbinfo, $path) = @_;
 
101
 
 
102
    unless (-e $path.'.work') {
 
103
        until (rename($path, $path.'.work')) {
 
104
            if ($! == ENOENT) {
 
105
                sleep(1);
 
106
                return if $need_exit;
 
107
            } else {
 
108
                print STDERR "error: Couldn't move $path to $path.work: $!\n";
 
109
                exit 1;
 
110
            }
 
111
        }
 
112
    }
 
113
 
 
114
    open(FILE, "+< $path.work") or die "error: Couldn't open $path.work: $!\n";
 
115
    setlock(\*FILE) or die "error: Couldn't lock $path.work: $!\n";
 
116
 
 
117
    while (<FILE>) {
 
118
        chomp(my $query = $_);
 
119
        until ($dbinfo->{handle}->do($query)) {
 
120
            print $dbinfo->{handle}->errstr."\n";
 
121
            if ($dbinfo->{handle}->ping) {
 
122
                sleep (1);
 
123
            } else {
 
124
                print "error: Lost connection to database\n";
 
125
                $dbinfo->{handle}->disconnect;
 
126
                connect_wait($dbinfo);
 
127
            }
 
128
        }
 
129
    }
 
130
 
 
131
    unlink($path.'.work');
 
132
    close(FILE); # and unlock
 
133
}
 
134
 
 
135
# sub main()
 
136
 
 
137
my %args = (
 
138
            b => 'radius',
 
139
            d => 'mysql',
 
140
            h => 'localhost',
 
141
            p => 'radius',
 
142
            u => 'radius',
 
143
);
 
144
my $ret = getopts("b:d:fh:P:p:u:x1?", \%args);
 
145
if (!$ret or @ARGV != 1) {
 
146
    usage();
 
147
    exit 1;
 
148
}
 
149
if ($args{'?'}) {
 
150
    usage();
 
151
    exit 0;
 
152
}
 
153
 
 
154
my $data_source;
 
155
if (lc($args{d}) eq 'mysql') {
 
156
    $data_source = "DBI:mysql:database=$args{b};host=$args{h}";
 
157
} elsif (lc($args{d}) eq 'pg') {
 
158
    $data_source = "DBI:Pg:dbname=$args{b};host=$args{h}";
 
159
} elsif (lc($args{d}) eq 'oracle') {
 
160
    $data_source = "DBI:Oracle:$args{b}";
 
161
} else {
 
162
    print STDERR "error: SQL driver not supported yet: $args{d}\n";
 
163
    exit 1;
 
164
}
 
165
$data_source .= ";port=$args{P}" if $args{'P'};
 
166
 
 
167
$SIG{INT} = \&got_signal;
 
168
$SIG{TERM} = \&got_signal;
 
169
 
 
170
my %dbinfo = (
 
171
              base => $data_source,
 
172
              user => $args{u},
 
173
              pass => $args{p},
 
174
);
 
175
connect_wait(\%dbinfo);
 
176
 
 
177
my $path = shift @ARGV;
 
178
 
 
179
until ($need_exit) {
 
180
    process_file(\%dbinfo, $path);
 
181
    last if ($args{1} || $need_exit);
 
182
    sleep(10);
 
183
}
 
184
 
 
185
$dbinfo{handle}->disconnect;