xref: /openbsd-src/gnu/usr.bin/perl/cpan/Sys-Syslog/win32/compile.pl (revision 6fb12b7054efc6b436584db6cef9c2f85c0d7e27)
1b39c5158Smillert#!perl
2b39c5158Smillertuse strict;
3b39c5158Smillertuse warnings;
4b39c5158Smillertuse File::Basename;
5b39c5158Smillertuse File::Copy;
6b39c5158Smillertuse File::Path;
7b39c5158Smillert
8b39c5158Smillertmy $name = shift || 'PerlLog';
9b39c5158Smillert
10b39c5158Smillert# get the version from the message file
11b39c5158Smillertopen(my $msgfh, '<', "$name.mc") or die "fatal: Can't read file '$name.mc': $!\n";
12b39c5158Smillertmy $top = <$msgfh>;
13b39c5158Smillertclose($msgfh);
14b39c5158Smillert
15b39c5158Smillertmy ($version) = $top =~ /Sys::Syslog Message File (\d+\.\d+\.\d+)/
16b39c5158Smillert        or die "error: File '$name.mc' doesn't have a version number\n";
17b39c5158Smillert
18b39c5158Smillert# compile the message text files
19b39c5158Smillertsystem("mc -d $name.mc");
20b39c5158Smillertsystem("rc $name.rc");
21b39c5158Smillertsystem(qq{ link -nodefaultlib -incremental:no -release /nologo -base:0x60000000 }
22b39c5158Smillert      .qq{ -comment:"Perl Syslog Message File v$version" }
23b39c5158Smillert      .qq{ -machine:i386 -dll -noentry -out:$name.dll $name.res });
24b39c5158Smillert
25b39c5158Smillert# uuencode the resource file
26b39c5158Smillertopen(my $rsrc, '<', "$name.RES") or die "fatal: Can't read resource file '$name.RES': $!";
27b39c5158Smillertbinmode($rsrc);
28b39c5158Smillertmy $uudata = pack "u", do { local $/; <$rsrc> };
29b39c5158Smillertclose($rsrc);
30b39c5158Smillert
31b39c5158Smillertopen(my $uufh, '>', "$name\_RES.uu") or die "fatal: Can't write file '$name\_RES.uu': $!";
32b39c5158Smillertprint $uufh $uudata;
33b39c5158Smillertclose($uufh);
34b39c5158Smillert
35b39c5158Smillert# uuencode the DLL
36b39c5158Smillertopen(my $dll, '<', "$name.dll") or die "fatal: Can't read DLL '$name.dll': $!";
37b39c5158Smillertbinmode($dll);
38b39c5158Smillert$uudata = pack "u", do { local $/; <$dll> };
39b39c5158Smillertclose($dll);
40b39c5158Smillert
41b39c5158Smillertopen($uufh, '>', "$name\_dll.uu") or die "fatal: Can't write file '$name\_dll.uu': $!";
42b39c5158Smillertprint $uufh $uudata;
43b39c5158Smillertclose($uufh);
44b39c5158Smillert
45b39c5158Smillert# parse the generated header to extract the constants
46b39c5158Smillertopen(my $header, '<', "$name.h") or die "fatal: Can't read header file '$name.h': $!";
47b39c5158Smillertmy %vals;
48b39c5158Smillertmy $max = 0;
49b39c5158Smillert
50b39c5158Smillertwhile (<$header>) {
51b39c5158Smillert    if (/^#define\s+(\w+)\s+(\d+)$/ || /^#define\s+(\w+)\s+\(\(DWORD\)(\d+)L\)/) {
52b39c5158Smillert        $vals{$1} = $2;
53b39c5158Smillert        if (substr($1, 0, 1) eq 'C') {
54b39c5158Smillert            $max = $2 if $max < $2;
55b39c5158Smillert        }
56b39c5158Smillert    }
57b39c5158Smillert}
58b39c5158Smillert
59b39c5158Smillertclose($header);
60b39c5158Smillert
61b39c5158Smillertmy ($hash, $f2c, %fac);
62b39c5158Smillert
63b39c5158Smillertfor my $name (sort { substr($a,0,1) cmp substr($b,0,1) || $vals{$a} <=> $vals{$b} } keys %vals) {
64b39c5158Smillert    $hash .= "    $name => $vals{$name},\n" ;
65b39c5158Smillert    if ($name =~ /^CAT_(\w+)$/) {
66b39c5158Smillert        $fac{$1} = $vals{$name};
67b39c5158Smillert    }
68b39c5158Smillert}
69b39c5158Smillert
70b39c5158Smillertfor my $name (sort {$fac{$a} <=> $fac{$b}} keys %fac) {
71b39c5158Smillert    $f2c .= "    Sys::Syslog::LOG_$name() => '$name',\n";
72b39c5158Smillert}
73b39c5158Smillert
74b39c5158Smillert# write the Sys::Syslog::Win32 module
75b39c5158Smillertopen my $out, '>', "Win32.pm" or die "fatal: Can't write Win32.pm: $!";
76b39c5158Smillertmy $template = join '', <DATA>;
77b39c5158Smillert$template =~ s/__CONSTANT__/$hash/;
78b39c5158Smillert$template =~ s/__F2C__/$f2c/;
79b39c5158Smillert$template =~ s/__NAME_VER__/$name/;
80b39c5158Smillert$template =~ s/__VER__/$version/;
81b39c5158Smillert$max = sprintf "0x%08x", $max;
82b39c5158Smillert$template =~ s/__MAX__/'$max'/g;
83b39c5158Smillert$template =~ s/__TIME__/localtime()/ge;
84b39c5158Smillertprint $out $template;
85b39c5158Smillertclose $out;
8691f110e0Safresh1print "Updated Win32.pm and relevant message files\n";
87b39c5158Smillert
88b39c5158Smillert__END__
89b39c5158Smillertpackage Sys::Syslog::Win32;
90b39c5158Smillertuse strict;
91b39c5158Smillertuse warnings;
92b39c5158Smillertuse Carp;
93b39c5158Smillertuse File::Spec;
94b39c5158Smillert
95b39c5158Smillert# === WARNING === WARNING === WARNING === WARNING === WARNING === WARNING ===
96b39c5158Smillert#
97b39c5158Smillert# This file was generated by Sys-Syslog/win32/compile.pl on __TIME__
98b39c5158Smillert# Any changes being made here will be lost the next time Sys::Syslog
99b39c5158Smillert# is installed.
100b39c5158Smillert#
101b39c5158Smillert# Do NOT USE THIS MODULE DIRECTLY: this is a utility module for Sys::Syslog.
102b39c5158Smillert# It may change at any time to fit the needs of Sys::Syslog therefore no
103b39c5158Smillert# warranty is made WRT to its API. You Have Been Warned.
104b39c5158Smillert#
105b39c5158Smillert# === WARNING === WARNING === WARNING === WARNING === WARNING === WARNING ===
106b39c5158Smillert
107b39c5158Smillertour $Source;
108b39c5158Smillertmy $logger;
109b39c5158Smillertmy $Registry;
110b39c5158Smillert
111b39c5158Smillertuse Win32::EventLog;
112b39c5158Smillertuse Win32::TieRegistry 0.20 (
113b39c5158Smillert    TiedRef     => \$Registry,
114b39c5158Smillert    Delimiter   => "/",
115b39c5158Smillert    ArrayValues => 1,
116b39c5158Smillert    SplitMultis => 1,
117b39c5158Smillert    AllowLoad   => 1,
118b39c5158Smillert    qw(
119b39c5158Smillert        REG_SZ
120b39c5158Smillert        REG_EXPAND_SZ
121b39c5158Smillert        REG_DWORD
122b39c5158Smillert        REG_BINARY
123b39c5158Smillert        REG_MULTI_SZ
124b39c5158Smillert        KEY_READ
125b39c5158Smillert        KEY_WRITE
126b39c5158Smillert        KEY_ALL_ACCESS
127b39c5158Smillert    ),
128b39c5158Smillert);
129b39c5158Smillert
130b39c5158Smillertmy $is_Cygwin = $^O =~ /Cygwin/i;
131b39c5158Smillertmy $is_Win32  = $^O =~ /Win32/i;
132b39c5158Smillert
133b39c5158Smillertmy %const = (
134b39c5158Smillert__CONSTANT__
135b39c5158Smillert);
136b39c5158Smillert
137b39c5158Smillertmy %id2name = (
138b39c5158Smillert__F2C__
139b39c5158Smillert);
140b39c5158Smillert
141b39c5158Smillertmy @priority2eventtype = (
142b39c5158Smillert    EVENTLOG_ERROR_TYPE(),       # LOG_EMERG
143b39c5158Smillert    EVENTLOG_ERROR_TYPE(),       # LOG_ALERT
144b39c5158Smillert    EVENTLOG_ERROR_TYPE(),       # LOG_CRIT
145b39c5158Smillert    EVENTLOG_ERROR_TYPE(),       # LOG_ERR
146b39c5158Smillert    EVENTLOG_WARNING_TYPE(),     # LOG_WARNING
147b39c5158Smillert    EVENTLOG_WARNING_TYPE(),     # LOG_NOTICE
148b39c5158Smillert    EVENTLOG_INFORMATION_TYPE(), # LOG_INFO
149b39c5158Smillert    EVENTLOG_INFORMATION_TYPE(), # LOG_DEBUG
150b39c5158Smillert);
151b39c5158Smillert
152b39c5158Smillert
153b39c5158Smillert#
154b39c5158Smillert# _install()
155b39c5158Smillert# --------
156b39c5158Smillert# Used to set up a connection to the eventlog.
157b39c5158Smillert#
158b39c5158Smillertsub _install {
159b39c5158Smillert    return $logger if $logger;
160b39c5158Smillert
161b39c5158Smillert    # can't just use basename($0) here because Win32 path often are a
162b39c5158Smillert    # a mix of / and \, and File::Basename::fileparse() can't handle that,
163b39c5158Smillert    # while File::Spec::splitpath() can.. Go figure..
164b39c5158Smillert    my (undef, undef, $basename) = File::Spec->splitpath($0);
165b39c5158Smillert    ($Source) ||= $basename;
166b39c5158Smillert
167b39c5158Smillert    $Source.=" [SSW:__VER__]";
168b39c5158Smillert
169b39c5158Smillert    #$Registry->Delimiter("/"); # is this needed?
170b39c5158Smillert    my $root = 'LMachine/SYSTEM/CurrentControlSet/Services/Eventlog/Application/';
171b39c5158Smillert    my $dll  = 'Sys/Syslog/__NAME_VER__.dll';
172b39c5158Smillert
173b39c5158Smillert    if (!$Registry->{$root.$Source} ||
174b39c5158Smillert        !$Registry->{$root.$Source.'/CategoryMessageFile'}[0] ||
175b39c5158Smillert        !-e $Registry->{$root.$Source.'/CategoryMessageFile'}[0] )
176b39c5158Smillert    {
177b39c5158Smillert
178b39c5158Smillert        # find the resource DLL, which should be along Syslog.dll
179b39c5158Smillert        my ($file) = grep { -e $_ }  map { ("$_/$dll" => "$_/auto/$dll") }  @INC;
180b39c5158Smillert        $dll = $file if $file;
181b39c5158Smillert
182b39c5158Smillert        # on Cygwin, convert the Unix path into absolute Windows path
183b39c5158Smillert        if ($is_Cygwin) {
184b39c5158Smillert            if ($] > 5.009005) {
185b39c5158Smillert                chomp($file = Cygwin::posix_to_win_path($file, 1));
186b39c5158Smillert            }
187b39c5158Smillert            else {
188b39c5158Smillert                local $ENV{PATH} = '';
189b39c5158Smillert                chomp($dll = `/usr/bin/cygpath --absolute --windows "$dll"`);
190b39c5158Smillert            }
191b39c5158Smillert        }
192b39c5158Smillert
193b39c5158Smillert        $dll =~ s![\\/]+!\\!g;     # must be backslashes!
194b39c5158Smillert        die "fatal: Can't find resource DLL for Sys::Syslog\n" if !$dll;
195b39c5158Smillert
196b39c5158Smillert        $Registry->{$root.$Source} = {
197b39c5158Smillert            '/EventMessageFile'    => [ $dll, REG_EXPAND_SZ ],
198b39c5158Smillert            '/CategoryMessageFile' => [ $dll, REG_EXPAND_SZ ],
199b39c5158Smillert            '/CategoryCount'       => [ __MAX__, REG_DWORD ],
200b39c5158Smillert            #'/TypesSupported'      => [ __MAX__, REG_DWORD ],
201b39c5158Smillert        };
202b39c5158Smillert
203b39c5158Smillert        warn "Configured eventlog to use $dll for $Source\n" if $Sys::Syslog::DEBUG;
204b39c5158Smillert    }
205b39c5158Smillert
206b39c5158Smillert    #Carp::confess("Registry has the wrong value for '$Source', possibly mismatched dll!\nMine:$dll\nGot :$Registry->{$root.$Source.'/CategoryMessageFile'}[0]\n")
207b39c5158Smillert    #    if $Registry->{$root.$Source.'/CategoryMessageFile'}[0] ne $dll;
208b39c5158Smillert
209b39c5158Smillert    # we really should do something useful with this but for now
210b39c5158Smillert    # we set it to "" to prevent Win32::EventLog from warning
211b39c5158Smillert    my $host = "";
212b39c5158Smillert
213b39c5158Smillert    $logger = Win32::EventLog->new($Source, $host)
214b39c5158Smillert        or Carp::confess("Failed to connect to the '$Source' event log");
215b39c5158Smillert
216b39c5158Smillert    return $logger;
217b39c5158Smillert}
218b39c5158Smillert
219b39c5158Smillert
220b39c5158Smillert#
221b39c5158Smillert# _syslog_send()
222b39c5158Smillert# ------------
223b39c5158Smillert# Used to convert syslog messages into eventlog messages
224b39c5158Smillert#
225b39c5158Smillertsub _syslog_send {
226b39c5158Smillert    my ($buf, $numpri, $numfac) = @_;
227b39c5158Smillert    $numpri ||= EVENTLOG_INFORMATION_TYPE();
228b39c5158Smillert    $numfac ||= Sys::Syslog::LOG_USER();
229b39c5158Smillert    my $name = $id2name{$numfac};
230b39c5158Smillert
231b39c5158Smillert    my $opts = {
232b39c5158Smillert        EventType   => $priority2eventtype[$numpri],
233b39c5158Smillert        EventID     => $const{"MSG_$name"},
234b39c5158Smillert        Category    => $const{"CAT_$name"},
235b39c5158Smillert        Strings     => "$buf\0",
236b39c5158Smillert        Data        => "",
237b39c5158Smillert    };
238b39c5158Smillert
239b39c5158Smillert    if ($Sys::Syslog::DEBUG) {
240b39c5158Smillert        require Data::Dumper;
241b39c5158Smillert        warn Data::Dumper->Dump(
242b39c5158Smillert            [$numpri, $numfac, $name, $opts],
243b39c5158Smillert            [qw(numpri numfac name opts)]
244b39c5158Smillert        );
245b39c5158Smillert    }
246b39c5158Smillert
247b39c5158Smillert    return $logger->Report($opts);
248b39c5158Smillert}
249b39c5158Smillert
250b39c5158Smillert
251b39c5158Smillert=head1 NAME
252b39c5158Smillert
253b39c5158SmillertSys::Syslog::Win32 - Win32 support for Sys::Syslog
254b39c5158Smillert
255b39c5158Smillert=head1 DESCRIPTION
256b39c5158Smillert
257b39c5158SmillertThis module is a back-end plugin for C<Sys::Syslog>, for supporting the Win32
258b39c5158Smillertevent log. It is not expected to be directly used by any module other than
259b39c5158SmillertC<Sys::Syslog> therefore it's API may change at any time and no warranty is
260b39c5158Smillertmade with regards to backward compatibility. You Have Been Warned.
261b39c5158Smillert
262*6fb12b70Safresh1In order to execute this script and compile the Win32 support files, you
263*6fb12b70Safresh1need some helper programs: mc.exe, rc.exe and link.exe
264*6fb12b70Safresh1
265*6fb12b70Safresh1mc.exe and rc.exe can be downloaded from
266*6fb12b70Safresh1http://www.microsoft.com/en-us/download/details.aspx?id=11310
267*6fb12b70Safresh1
268*6fb12b70Safresh1link.exe is usually shipped with Visual Studio.
269*6fb12b70Safresh1
270b39c5158Smillert=head1 SEE ALSO
271b39c5158Smillert
272b39c5158SmillertL<Sys::Syslog>
273b39c5158Smillert
274b39c5158Smillert=head1 AUTHORS
275b39c5158Smillert
276b39c5158SmillertSE<eacute>bastien Aperghis-Tramoni and Yves Orton
277b39c5158Smillert
278b39c5158Smillert=head1 LICENSE
279b39c5158Smillert
280b39c5158SmillertThis program is free software; you can redistribute it and/or modify it
281b39c5158Smillertunder the same terms as Perl itself.
282b39c5158Smillert
283b39c5158Smillert=cut
284b39c5158Smillert
285b39c5158Smillert1;
286