File: init.pl

package info (click to toggle)
atheme-services 7.2.12-2.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 17,256 kB
  • sloc: ansic: 95,899; sh: 8,462; php: 5,032; perl: 3,327; makefile: 1,279; sed: 16; ruby: 15; python: 3
file content (117 lines) | stat: -rw-r--r-- 2,759 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package Atheme::Init;

=head1 init.pl -- perl initialisation for Atheme.

This file is processed on initialising the perl interpreter in C<perl.so>. It is
mainly concerned with setting up the Perl environment, maintaining the list of
loaded perl scripts, and providing the means to load and unload them.

=cut

use strict;
use warnings;

use FindBin;
use Symbol qw(delete_package);

use lib "$FindBin::Bin";

use Atheme;
use Atheme::Internal;

our %Scripts;

sub package_name_ify {
    my ($filename) = @_;

    $filename =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg;
    # second pass only for words starting with a digit
    $filename =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg;

    # Dress it up as a real package name
    $filename =~ s|/|::|g;
    return "Embed" . $filename;
}

sub load_script {
    my ($filename, $message, $nonfatal) = @_;
    my $packagename = package_name_ify($filename);

    if (defined $Scripts{$packagename})
    {
        if ($nonfatal) {
            $message->reply("$filename is already loaded");
            return;
        }

        # This will always be called with G_EVAL, so this die can be translated
        # into a load error in the C module.
        die "$filename is already loaded.";
    }

    local *FH;
    open FH, $filename or die "Couldn't open $filename: $!";
    local ($/) = undef;
    my $script_text = <FH>;
    close FH;

    # Must all be on one line here to avoid messing up line numbers in error
    # messages.
    my $eval = "package $packagename; our %Info; $script_text";
    {
        my ($filename, $packagename, $script_text);
        eval $eval;
    }
    if ($@) {
        delete_package $packagename;
        die $@;
    }

    $Scripts{$packagename} = $filename;
    return $packagename;
}

sub unload_script {
    my ($filename, $message) = @_;
    my $packagename = package_name_ify($filename);

    if (!defined $Scripts{$packagename})
    {
        die "$filename is not loaded";
    }

    eval "${packagename}::unload(\$message)";

    Atheme::Internal::unbind_commands($packagename);
    Atheme::Hooks::unbind_hooks($packagename);

    delete_package($packagename);
    delete $Scripts{$packagename};
}

sub list_scripts {
    my ($si) = @_;
    $si->success("Loaded scripts:");
    my $num = 0;
    foreach my $script (values %Scripts) {
            $num++;
            $si->success("$num: $script");
    }
    $si->success("\x02$num\x02 scripts loaded.");
}

sub call_wrapper {
    my $sub = shift;
    my $saved_alarm=$SIG{ALRM};
    $SIG{ALRM} = sub { die "Script used too much running time"; };
    my $ret;
    eval {
            alarm 1;
            $ret = &$sub(@_);
    };
    alarm 0;
    $SIG{ALRM} = $saved_alarm;
    die $@ if $@;
    return $ret;
}