OLD | NEW |
| (Empty) |
1 #!/usr/bin/perl -w | |
2 # This script was originally based on the script of the same name from | |
3 # the KDE SDK (by dfaure@kde.org) | |
4 # | |
5 # This version is | |
6 # Copyright (C) 2007, 2008 Adam D. Barratt | |
7 # | |
8 # This program is free software; you can redistribute it and/or modify | |
9 # it under the terms of the GNU General Public License as published by | |
10 # the Free Software Foundation; either version 2 of the License, or | |
11 # (at your option) any later version. | |
12 # | |
13 # This program is distributed in the hope that it will be useful, | |
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 # GNU General Public License for more details. | |
17 # | |
18 # You should have received a copy of the GNU General Public License along | |
19 # with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 | |
21 =head1 NAME | |
22 | |
23 licensecheck - simple license checker for source files | |
24 | |
25 =head1 SYNOPSIS | |
26 | |
27 B<licensecheck> B<--help>|B<--version> | |
28 | |
29 B<licensecheck> [B<--no-conf>] [B<--verbose>] [B<--copyright>] | |
30 [B<-l>|B<--lines=>I<N>] [B<-i>|B<--ignore=>I<regex>] [B<-c>|B<--check=>I<regex>] | |
31 [B<-r>|B<--recursive>] I<list of files and directories to check> | |
32 | |
33 =head1 DESCRIPTION | |
34 | |
35 B<licensecheck> attempts to determine the license that applies to each file | |
36 passed to it, by searching the start of the file for text belonging to | |
37 various licenses. | |
38 | |
39 If any of the arguments passed are directories, B<licensecheck> will add | |
40 the files contained within to the list of files to process. | |
41 | |
42 =head1 OPTIONS | |
43 | |
44 =over 4 | |
45 | |
46 =item B<--verbose>, B<--no-verbose> | |
47 | |
48 Specify whether to output the text being processed from each file before | |
49 the corresponding license information. | |
50 | |
51 Default is to be quiet. | |
52 | |
53 =item B<-l=>I<N>, B<--lines=>I<N> | |
54 | |
55 Specify the number of lines of each file's header which should be parsed | |
56 for license information. (Default is 60). | |
57 | |
58 =item B<-i=>I<regex>, B<--ignore=>I<regex> | |
59 | |
60 When processing the list of files and directories, the regular | |
61 expression specified by this option will be used to indicate those which | |
62 should not be considered (e.g. backup files, VCS metadata). | |
63 | |
64 =item B<-r>, B<--recursive> | |
65 | |
66 Specify that the contents of directories should be added | |
67 recursively. | |
68 | |
69 =item B<-c=>I<regex>, B<--check=>I<regex> | |
70 | |
71 Specify a pattern against which filenames will be matched in order to | |
72 decide which files to check the license of. | |
73 | |
74 The default includes common source files. | |
75 | |
76 =item B<--copyright> | |
77 | |
78 Also display copyright text found within the file | |
79 | |
80 =item B<--no-conf>, B<--noconf> | |
81 | |
82 Do not read any configuration files. This can only be used as the first | |
83 option given on the command-line. | |
84 | |
85 =back | |
86 | |
87 =head1 CONFIGURATION VARIABLES | |
88 | |
89 The two configuration files F</etc/devscripts.conf> and | |
90 F<~/.devscripts> are sourced by a shell in that order to set | |
91 configuration variables. Command line options can be used to override | |
92 configuration file settings. Environment variable settings are | |
93 ignored for this purpose. The currently recognised variables are: | |
94 | |
95 =over 4 | |
96 | |
97 =item B<LICENSECHECK_VERBOSE> | |
98 | |
99 If this is set to I<yes>, then it is the same as the B<--verbose> command | |
100 line parameter being used. The default is I<no>. | |
101 | |
102 =item B<LICENSECHECK_PARSELINES> | |
103 | |
104 If this is set to a positive number then the specified number of lines | |
105 at the start of each file will be read whilst attempting to determine | |
106 the license(s) in use. This is equivalent to the B<--lines> command line | |
107 option. | |
108 | |
109 =back | |
110 | |
111 =head1 LICENSE | |
112 | |
113 This code is copyright by Adam D. Barratt <I<adam@adam-barratt.org.uk>>, | |
114 all rights reserved; based on a script of the same name from the KDE | |
115 SDK, which is copyright by <I<dfaure@kde.org>>. | |
116 This program comes with ABSOLUTELY NO WARRANTY. | |
117 You are free to redistribute this code under the terms of the GNU | |
118 General Public License, version 2 or later. | |
119 | |
120 =head1 AUTHOR | |
121 | |
122 Adam D. Barratt <adam@adam-barratt.org.uk> | |
123 | |
124 =cut | |
125 | |
126 use strict; | |
127 use warnings; | |
128 use Getopt::Long qw(:config gnu_getopt); | |
129 use File::Basename; | |
130 | |
131 sub fatal($); | |
132 sub parse_copyright($); | |
133 sub parselicense($); | |
134 | |
135 my $progname = basename($0); | |
136 | |
137 # From dpkg-source | |
138 my $default_ignore_regex = ' | |
139 # Ignore general backup files | |
140 (?:^|/).*~$| | |
141 # Ignore emacs recovery files | |
142 (?:^|/)\.#.*$| | |
143 # Ignore vi swap files | |
144 (?:^|/)\..*\.swp$| | |
145 # Ignore baz-style junk files or directories | |
146 (?:^|/),,.*(?:$|/.*$)| | |
147 # File-names that should be ignored (never directories) | |
148 (?:^|/)(?:DEADJOE|\.cvsignore|\.arch-inventory|\.bzrignore|\.gitignore)$| | |
149 # File or directory names that should be ignored | |
150 (?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|\.hg|_darcs|\.git| | |
151 \.shelf|_MTN|\.bzr(?:\.backup|tags)?)(?:$|/.*$) | |
152 '; | |
153 | |
154 # Take out comments and newlines | |
155 $default_ignore_regex =~ s/^#.*$//mg; | |
156 $default_ignore_regex =~ s/\n//sg; | |
157 | |
158 my $default_check_regex = '\.(c(c|pp|xx)?|h(h|pp|xx)?|f(77|90)?|p(l|m)|xs|sh|php
|py|rb|java|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod)$'; | |
159 | |
160 my $modified_conf_msg; | |
161 | |
162 my ($opt_verbose, $opt_lines, $opt_noconf, $opt_ignore_regex, $opt_check_regex) | |
163 = ('', '', '', '', ''); | |
164 my $opt_recursive = 0; | |
165 my $opt_copyright = 0; | |
166 my ($opt_help, $opt_version); | |
167 my $def_lines = 60; | |
168 | |
169 # Read configuration files and then command line | |
170 # This is boilerplate | |
171 | |
172 if (@ARGV and $ARGV[0] =~ /^--no-?conf$/) { | |
173 $modified_conf_msg = " (no configuration files read)"; | |
174 shift; | |
175 } else { | |
176 my @config_files = ('/etc/devscripts.conf', '~/.devscripts'); | |
177 my %config_vars = ( | |
178 'LICENSECHECK_VERBOSE' => 'no', | |
179 'LICENSECHECK_PARSELINES' => $def_lines, | |
180 ); | |
181 my %config_default = %config_vars; | |
182 | |
183 my $shell_cmd; | |
184 # Set defaults | |
185 foreach my $var (keys %config_vars) { | |
186 $shell_cmd .= qq[$var="$config_vars{$var}";\n]; | |
187 } | |
188 $shell_cmd .= 'for file in ' . join(" ", @config_files) . "; do\n"; | |
189 $shell_cmd .= '[ -f $file ] && . $file; done;' . "\n"; | |
190 # Read back values | |
191 foreach my $var (keys %config_vars) { $shell_cmd .= "echo \$$var;\n" } | |
192 my $shell_out = `/bin/bash -c '$shell_cmd'`; | |
193 @config_vars{keys %config_vars} = split /\n/, $shell_out, -1; | |
194 | |
195 # Check validity | |
196 $config_vars{'LICENSECHECK_VERBOSE'} =~ /^(yes|no)$/ | |
197 or $config_vars{'LICENSECHECK_VERBOSE'} = 'no'; | |
198 $config_vars{'LICENSECHECK_PARSELINES'} =~ /^[1-9][0-9]*$/ | |
199 or $config_vars{'LICENSECHECK_PARSELINES'} = $def_lines; | |
200 | |
201 foreach my $var (sort keys %config_vars) { | |
202 if ($config_vars{$var} ne $config_default{$var}) { | |
203 $modified_conf_msg .= " $var=$config_vars{$var}\n"; | |
204 } | |
205 } | |
206 $modified_conf_msg ||= " (none)\n"; | |
207 chomp $modified_conf_msg; | |
208 | |
209 $opt_verbose = $config_vars{'LICENSECHECK_VERBOSE'} eq 'yes' ? 1 : 0; | |
210 $opt_lines = $config_vars{'LICENSECHECK_PARSELINES'}; | |
211 } | |
212 | |
213 GetOptions("help|h" => \$opt_help, | |
214 "version|v" => \$opt_version, | |
215 "verbose!" => \$opt_verbose, | |
216 "lines|l=i" => \$opt_lines, | |
217 "ignore|i=s" => \$opt_ignore_regex, | |
218 "recursive|r" => \$opt_recursive, | |
219 "check|c=s" => \$opt_check_regex, | |
220 "copyright" => \$opt_copyright, | |
221 "noconf" => \$opt_noconf, | |
222 "no-conf" => \$opt_noconf, | |
223 ) | |
224 or die "Usage: $progname [options] filelist\nRun $progname --help for more d
etails\n"; | |
225 | |
226 $opt_lines = $def_lines if $opt_lines !~ /^[1-9][0-9]*$/; | |
227 $opt_ignore_regex = $default_ignore_regex if ! length $opt_ignore_regex; | |
228 $opt_check_regex = $default_check_regex if ! length $opt_check_regex; | |
229 | |
230 if ($opt_noconf) { | |
231 fatal "--no-conf is only acceptable as the first command-line option!"; | |
232 } | |
233 if ($opt_help) { help(); exit 0; } | |
234 if ($opt_version) { version(); exit 0; } | |
235 | |
236 die "Usage: $progname [options] filelist\nRun $progname --help for more details\
n" unless @ARGV; | |
237 | |
238 $opt_lines = $def_lines if not defined $opt_lines; | |
239 | |
240 my @files = (); | |
241 my @find_args = (); | |
242 my $files_count = @ARGV; | |
243 | |
244 push @find_args, qw(-maxdepth 1) unless $opt_recursive; | |
245 push @find_args, qw(-follow -type f -print); | |
246 | |
247 while (@ARGV) { | |
248 my $file = shift @ARGV; | |
249 | |
250 if (-d $file) { | |
251 open FIND, '-|', 'find', $file, @find_args | |
252 or die "$progname: couldn't exec find: $!\n"; | |
253 | |
254 while (<FIND>) { | |
255 chomp; | |
256 next unless m%$opt_check_regex%; | |
257 # Skip empty files | |
258 next if (-z $_); | |
259 push @files, $_ unless m%$opt_ignore_regex%; | |
260 } | |
261 close FIND; | |
262 } else { | |
263 next unless ($files_count == 1) or $file =~ m%$opt_check_regex%; | |
264 push @files, $file unless $file =~ m%$opt_ignore_regex%; | |
265 } | |
266 } | |
267 | |
268 while (@files) { | |
269 my $file = shift @files; | |
270 my $content = ''; | |
271 my $copyright_match; | |
272 my $copyright = ''; | |
273 my $license = ''; | |
274 my %copyrights; | |
275 | |
276 open (F, "<$file") or die "Unable to access $file\n"; | |
277 while (<F>) { | |
278 last if ($. > $opt_lines); | |
279 $content .= $_; | |
280 $copyright_match = parse_copyright($_); | |
281 if ($copyright_match) { | |
282 $copyrights{lc("$copyright_match")} = "$copyright_match"; | |
283 } | |
284 } | |
285 close(F); | |
286 | |
287 $copyright = join(" / ", values %copyrights); | |
288 | |
289 print qq(----- $file header -----\n$content----- end header -----\n\n) | |
290 if $opt_verbose; | |
291 | |
292 $content =~ tr/\t\r\n/ /; | |
293 # Remove C / C++ comments | |
294 $content =~ s#(\*/|/[/*])##g; | |
295 $content =~ tr% A-Za-z.,@;0-9\(\)/-%%cd; | |
296 $content =~ s/ c //g; # Remove fortran comments | |
297 $content =~ tr/ //s; | |
298 | |
299 $license = parselicense($content); | |
300 print "$file: "; | |
301 print "*No copyright* " unless $copyright; | |
302 print $license . "\n"; | |
303 print " [Copyright: " . $copyright . "]\n" | |
304 if $copyright and $opt_copyright; | |
305 print "\n" if $opt_copyright; | |
306 } | |
307 | |
308 sub parse_copyright($) { | |
309 my $copyright = ''; | |
310 my $match; | |
311 | |
312 my $copyright_indicator_regex = ' | |
313 (?:copyright # The full word | |
314 |copr\. # Legally-valid abbreviation | |
315 |\x{00a9} # Unicode character COPYRIGHT SIGN | |
316 |\xc2\xa9 # Unicode copyright sign encoded in iso8859 | |
317 |\(c\) # Legally-null representation of sign | |
318 )'; | |
319 my $copyright_disindicator_regex = ' | |
320 \b(?:info(?:rmation)? # Discussing copyright information | |
321 |notice # Discussing the notice | |
322 |and|or # Part of a sentence | |
323 )\b'; | |
324 | |
325 if (m%$copyright_indicator_regex(?::\s*|\s+)(\S.*)$%ix) { | |
326 $match = $1; | |
327 | |
328 # Ignore lines matching "see foo for copyright information" etc. | |
329 if ($match !~ m%^\s*$copyright_disindicator_regex%ix) { | |
330 # De-cruft | |
331 $match =~ s/([,.])?\s*$//; | |
332 $match =~ s/$copyright_indicator_regex//igx; | |
333 $match =~ s/^\s+//; | |
334 $match =~ s/\s{2,}/ /g; | |
335 $match =~ s/\\@/@/g; | |
336 $copyright = $match; | |
337 } | |
338 } | |
339 | |
340 return $copyright; | |
341 } | |
342 | |
343 sub help { | |
344 print <<"EOF"; | |
345 Usage: $progname [options] filename [filename ...] | |
346 Valid options are: | |
347 --help, -h Display this message | |
348 --version, -v Display version and copyright info | |
349 --no-conf, --noconf Don't read devscripts config files; must be | |
350 the first option given | |
351 --verbose Display the header of each file before its | |
352 license information | |
353 --lines, -l Specify how many lines of the file header | |
354 should be parsed for license information | |
355 (Default: $def_lines) | |
356 --check, -c Specify a pattern indicating which files should | |
357 be checked | |
358 (Default: '$default_check_regex') | |
359 --recursive, -r Add the contents of directories recursively | |
360 --copyright Also display the file's copyright | |
361 --ignore, -i Specify that files / directories matching the | |
362 regular expression should be ignored when | |
363 checking files | |
364 (Default: '$default_ignore_regex') | |
365 | |
366 Default settings modified by devscripts configuration files: | |
367 $modified_conf_msg | |
368 EOF | |
369 } | |
370 | |
371 sub version { | |
372 print <<"EOF"; | |
373 This is $progname, from the Debian devscripts package, version ###VERSION### | |
374 Copyright (C) 2007, 2008 by Adam D. Barratt <adam\@adam-barratt.org.uk>; based | |
375 on a script of the same name from the KDE SDK by <dfaure\@kde.org>. | |
376 | |
377 This program comes with ABSOLUTELY NO WARRANTY. | |
378 You are free to redistribute this code under the terms of the | |
379 GNU General Public License, version 2, or (at your option) any | |
380 later version. | |
381 EOF | |
382 } | |
383 | |
384 sub parselicense($) { | |
385 my ($licensetext) = @_; | |
386 | |
387 my $gplver = ""; | |
388 my $extrainfo = ""; | |
389 my $license = ""; | |
390 | |
391 if ($licensetext =~ /version ([^ ]+) (?:\(?only\)?.? )?(?:of the GNU (Affero
)?General Public License )?as published by the Free Software Foundation/i or | |
392 $licensetext =~ /GNU (?:Affero )?General Public License as published by
the Free Software Foundation; version ([^ ]+) /i) { | |
393 | |
394 $gplver = " (v$1)"; | |
395 } elsif ($licensetext =~ /GNU (Affero ?)General Public License, version ([^
]+?)[ .]/) { | |
396 $gplver = " (v$1)"; | |
397 } elsif ($licensetext =~ /either version ([^ ]+) of the License, or \(at you
r option\) any later version/) { | |
398 $gplver = " (v$1 or later)"; | |
399 } | |
400 | |
401 if ($licensetext =~ /(?:675 Mass Ave|59 Temple Place|51 Franklin Steet|02139
|02111-1307)/i) { | |
402 $extrainfo = " (with incorrect FSF address)$extrainfo"; | |
403 } | |
404 | |
405 if ($licensetext =~ /permission (?:is (also granted|given))? to link (the co
de of )?this program with (any edition of )?(Qt|the Qt library)/i) { | |
406 $extrainfo = " (with Qt exception)$extrainfo" | |
407 } | |
408 | |
409 if ($licensetext =~ /(All changes made in this file will be lost|DO NOT (EDI
T|delete this file)|Generated (automatically|by|from)|generated.*file)/i) { | |
410 $license = "GENERATED FILE"; | |
411 } | |
412 | |
413 if ($licensetext =~ /is free software.? you can redistribute it and\/or modi
fy it under the terms of the (GNU (Library|Lesser) General Public License|LGPL)/
i) { | |
414 $license = "LGPL$gplver$extrainfo $license"; | |
415 } | |
416 | |
417 if ($licensetext =~ /is free software.? you can redistribute it and\/or modi
fy it under the terms of the (GNU Affero General Public License|AGPL)/i) { | |
418 $license = "AGPL$gplver$extrainfo $license"; | |
419 } | |
420 | |
421 if ($licensetext =~ /is free software.? you (can|may) redistribute it and\/o
r modify it under the terms of (?:version [^ ]+ (?:\(?only\)? )?of )?the GNU Gen
eral Public License/i) { | |
422 $license = "GPL$gplver$extrainfo $license"; | |
423 } | |
424 | |
425 if ($licensetext =~ /is distributed under the terms of the GNU General Publi
c License,/ | |
426 and length $gplver) { | |
427 $license = "GPL$gplver$extrainfo $license"; | |
428 } | |
429 | |
430 if ($licensetext =~ /is distributed.*terms.*GPL/) { | |
431 $license = "GPL (unversioned/unknown version) $license"; | |
432 } | |
433 | |
434 if ($licensetext =~ /This file is part of the .*Qt GUI Toolkit. This file ma
y be distributed under the terms of the Q Public License as defined/) { | |
435 $license = "QPL (part of Qt) $license"; | |
436 } elsif ($licensetext =~ /may be distributed under the terms of the Q Public
License as defined/) { | |
437 $license = "QPL $license"; | |
438 } | |
439 | |
440 if ($licensetext =~ /opensource\.org\/licenses\/mit-license\.php/) { | |
441 $license = "MIT/X11 (BSD like) $license"; | |
442 } elsif ($licensetext =~ /Permission is hereby granted, free of charge, to a
ny person obtaining a copy of this software and(\/or)? associated documentation
files \(the (Software|Materials)\), to deal in the (Software|Materials)/) { | |
443 $license = "MIT/X11 (BSD like) $license"; | |
444 } elsif ($licensetext =~ /Permission is hereby granted, without written agre
ement and without license or royalty fees, to use, copy, modify, and distribute
this software and its documentation for any purpose/) { | |
445 $license = "MIT/X11 (BSD like) $license"; | |
446 } | |
447 | |
448 if ($licensetext =~ /Permission to use, copy, modify, and(\/or)? distribute
this software for any purpose with or without fee is hereby granted, provided.*
copyright notice.*permission notice.*all copies/) { | |
449 $license = "ISC $license"; | |
450 } | |
451 | |
452 if ($licensetext =~ /THIS SOFTWARE IS PROVIDED .*AS IS AND ANY EXPRESS OR IM
PLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCH
ANTABILITY/) { | |
453 if ($licensetext =~ /All advertising materials mentioning features or us
e of this software must display the following acknowledge?ment.*This product inc
ludes software developed by/i) { | |
454 $license = "BSD (4 clause) $license"; | |
455 } elsif ($licensetext =~ /(The name .*? may not|Neither the names? .*? n
or the names of (its|their) contributors may) be used to endorse or promote prod
ucts derived from this software/i) { | |
456 $license = "BSD (3 clause) $license"; | |
457 } elsif ($licensetext =~ /Redistributions of source code must retain the
above copyright notice/i) { | |
458 $license = "BSD (2 clause) $license"; | |
459 } else { | |
460 $license = "BSD $license"; | |
461 } | |
462 } | |
463 | |
464 if ($licensetext =~ /Mozilla Public License Version ([^ ]+)/) { | |
465 $license = "MPL (v$1) $license"; | |
466 } | |
467 | |
468 if ($licensetext =~ /Released under the terms of the Artistic License ([^ ]+
)/) { | |
469 $license = "Artistic (v$1) $license"; | |
470 } | |
471 | |
472 if ($licensetext =~ /is free software under the Artistic [Ll]icense/) { | |
473 $license = "Artistic $license"; | |
474 } | |
475 | |
476 if ($licensetext =~ /This program is free software; you can redistribute it
and\/or modify it under the same terms as Perl itself/) { | |
477 $license = "Perl $license"; | |
478 } | |
479 | |
480 if ($licensetext =~ /under the Apache License, Version ([^ ]+)/) { | |
481 $license = "Apache (v$1) $license"; | |
482 } | |
483 | |
484 if ($licensetext =~ /This source file is subject to version ([^ ]+) of the P
HP license/) { | |
485 $license = "PHP (v$1) $license"; | |
486 } | |
487 | |
488 if ($licensetext =~ /under the terms of the CeCILL /) { | |
489 $license = "CeCILL $license"; | |
490 } | |
491 | |
492 if ($licensetext =~ /under the terms of the CeCILL-([^ ]+) /) { | |
493 $license = "CeCILL-$1 $license"; | |
494 } | |
495 | |
496 if ($licensetext =~ /under the SGI Free Software License B/) { | |
497 $license = "SGI Free Software License B $license"; | |
498 } | |
499 | |
500 if ($licensetext =~ /is in the public domain/i) { | |
501 $license = "Public domain"; | |
502 } | |
503 | |
504 if ($licensetext =~ /terms of the Common Development and Distribution Licens
e(, Version ([^(]+))? \(the License\)/) { | |
505 $license = "CDDL " . ($1 ? "(v$2) " : '') . $license; | |
506 } | |
507 | |
508 if ($licensetext =~ /Microsoft Permissive License \(Ms-PL\)/) { | |
509 $license = "Ms-PL $license"; | |
510 } | |
511 | |
512 if ($licensetext =~ /Permission is hereby granted, free of charge, to any pe
rson or organization obtaining a copy of the software and accompanying documenta
tion covered by this license \(the \"Software\"\)/ or | |
513 $licensetext =~ /Boost Software License([ ,-]+Version ([^ ]+)?(\.))/i) { | |
514 $license = "BSL " . ($1 ? "(v$2) " : '') . $license; | |
515 } | |
516 | |
517 if ($licensetext =~ /PYTHON SOFTWARE FOUNDATION LICENSE (VERSION ([^ ]+))/i)
{ | |
518 $license = "PSF " . ($1 ? "(v$2) " : '') . $license; | |
519 } | |
520 | |
521 if ($licensetext =~ /The origin of this software must not be misrepresented.
*Altered source versions must be plainly marked as such.*This notice may not be
removed or altered from any source distribution/ or | |
522 $licensetext =~ /see copyright notice in zlib\.h/) { | |
523 $license = "zlib/libpng $license"; | |
524 } elsif ($licensetext =~ /This code is released under the libpng license/) { | |
525 $license = "libpng $license"; | |
526 } | |
527 | |
528 if ($licensetext =~ /Do What The Fuck You Want To Public License, Version ([
^, ]+)/i) { | |
529 $license = "WTFPL (v$1)"; | |
530 } | |
531 | |
532 if ($licensetext =~ /Do what The Fuck You Want To Public License/i) { | |
533 $license = "WTFPL"; | |
534 } | |
535 | |
536 if ($licensetext =~ /(License WTFPL|Under (the|a) WTFPL)/i) { | |
537 $license = "WTFPL"; | |
538 } | |
539 | |
540 $license = "UNKNOWN" if (!length($license)); | |
541 | |
542 return $license; | |
543 } | |
544 | |
545 sub fatal($) { | |
546 my ($pack,$file,$line); | |
547 ($pack,$file,$line) = caller(); | |
548 (my $msg = "$progname: fatal error at line $line:\n@_\n") =~ tr/\0//d; | |
549 $msg =~ s/\n\n$/\n/; | |
550 die $msg; | |
551 } | |
OLD | NEW |