]> ruderich.org/simon Gitweb - config/dotfiles.git/blobdiff - shell/bin/print-constant.pl
Move to shell/ in preparation for merge into new dotfiles repository
[config/dotfiles.git] / shell / bin / print-constant.pl
diff --git a/shell/bin/print-constant.pl b/shell/bin/print-constant.pl
new file mode 100755 (executable)
index 0000000..f0205db
--- /dev/null
@@ -0,0 +1,258 @@
+#!/usr/bin/perl
+
+# Print values of C constants.
+
+# Copyright (C) 2012  Simon Ruderich
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+use strict;
+use warnings;
+
+use Getopt::Long ();
+use File::Temp ();
+
+our $VERSION = '0.01';
+
+
+my $option_help     = 0;
+my $option_version  = 0;
+my @option_include  = ();
+my $option_pathconf = undef;
+my $option_quiet    = 0;
+my $option_sysconf  = 0;
+my $option_type     = 'd';
+if (not Getopt::Long::GetOptions(
+            'help|h|?'     => \$option_help,
+            'version|v'    => \$option_version,
+            #
+            'include|i=s'  => \@option_include,
+            'pathconf|p=s' => \$option_pathconf,
+            'quiet|q'      => \$option_quiet,
+            'sysconf|s'    => \$option_sysconf,
+            'type|t=s'     => \$option_type,
+        )) {
+    require Pod::Usage;
+    Pod::Usage::pod2usage(2);
+}
+if ($option_help) {
+    require Pod::Usage;
+    Pod::Usage::pod2usage(1);
+}
+if ($option_version) {
+    print <<EOF;
+print-constant $VERSION  Copyright (C) 2012  Simon Ruderich
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+EOF
+    exit 0;
+}
+
+# We need the constant name as argument.
+if (scalar @ARGV != 1) {
+    require Pod::Usage;
+    Pod::Usage::pod2usage(2);
+}
+
+
+my $constant = $ARGV[0];
+# Check for non-constant name inputs - also prevents running arbitrary code on
+# the machine.
+if (not $constant =~ /^[a-zA-Z0-9_]+$/) {
+    print STDERR "Invalid constant name: '$constant'!\n";
+    exit 1;
+}
+
+# Some sanity checks.
+if (not $option_type =~ /^[a-zA-Z]+$/) {
+    print STDERR "Invalid type: '$option_type'!\n";
+    exit 1;
+}
+if ($option_sysconf and defined $option_pathconf) {
+    print STDERR "--sysconf and --pathconf can't be used together!\n";
+    exit 1;
+}
+foreach my $include (@option_include) {
+    if (not $include =~ m{^[a-zA-Z0-9./_-]+$}) {
+        print STDERR "Invalid include: '$include'!\n";
+        exit 1;
+    }
+}
+
+my $constant_display = $constant;
+# Pass the constant to sysconf()/pathconf() instead of using it directly.
+if ($option_sysconf) {
+    $constant = "sysconf($constant)";
+    $constant_display = $constant;
+} elsif (defined $option_pathconf) {
+    $constant_display = "pathconf(\"$option_pathconf\", $constant)";
+    # Use the current directory to prevent escape problems for the path, see
+    # below.
+    $constant = "pathconf(\".\", $constant)";
+}
+
+
+# Use "limits.h" and "unistd.h" as default include - but only if the user
+# specified no other includes, in case it conflicts with "limits.h".
+if (scalar @option_include == 0) {
+    push @option_include, 'limits.h';
+    push @option_include, 'unistd.h';
+}
+
+
+# Temporary directory where the following C program which prints the constant
+# is built.
+my $tempdir = File::Temp::tempdir(CLEANUP => 1) or die $!;
+chdir $tempdir or die $!;
+
+# Write the C file which prints the constant value.
+my $c_template = <<'EOF';
+#include <stdio.h>
+#include <stdlib.h>
+%s
+
+int main(int argc, char **argv) {
+    printf("%s\n", %s);
+
+    return EXIT_SUCCESS;
+}
+EOF
+open my $fh, '>', 'constant.c' or die $!;
+printf $fh $c_template,
+           join("\n", map { "#include <$_>" } @option_include),
+           '%' . $option_type,
+           $constant;
+close $fh or die $!;
+
+# Compile the constant C file.
+my @args = ('cc', '-o', 'constant', 'constant.c');
+if (system(@args) != 0) {
+    print STDERR "Compilation failure (message above).\n";
+
+    chdir; # see below
+    exit 1;
+}
+
+# pathconf() needs a path, we use the current directory - therefore we have to
+# chdir to the given path. This prevents escape problems with the path.
+if (defined $option_pathconf) {
+    chdir $option_pathconf;
+}
+
+my $value = `$tempdir/constant`;
+
+if ($option_quiet) {
+    print $value;
+} else {
+    print "$constant_display: $value";
+}
+
+# Change the working directory or File::Temp can't remove our temporary
+# directory.
+chdir;
+
+
+__END__
+
+=head1 NAME
+
+print-constant - print values of C constants
+
+=head1 SYNOPSIS
+
+B<print-constant> [I<options>] I<CONSTANT_NAME>
+
+=head1 DESCRIPTION
+
+print-constant prints the values of C constants. Useful to find out certain
+system constants without having to write a small C program to print them.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-i> I<include>, B<--include> I<include>
+
+Use I<include> as include file. Adds C<#include E<lt>includeE<gt>> to the
+beginning of the C file used to print the constant. By default C<limits.h> and
+C<unistd.h> are used as headers. If this option is specified I<no> default
+includes are used. Can be specified multiple times.
+
+=item B<-p> I<path>, B<--pathconf> I<path>
+
+Pass the constant to pathconf(3) and print the result. I<path> is the first
+argument for pathconf(3). Conflicts with B<--sysconf>.
+
+=item B<-q>, B<--quiet>
+
+Display only the constant's value.
+
+=item B<-s>, B<--sysconf>
+
+Pass the constant to sysconf(3) and print the result. Conflicts with
+B<--pathconf>.
+
+=item B<-t> I<type>, B<--type> I<type>
+
+Use I<type> as type of the constant, used in printf(3). By default C<d> is
+used.
+
+=item B<-h>, B<-?>, B<--help>
+
+Print available options.
+
+=item B<-v>, B<--version>
+
+Print version number and license.
+
+=back
+
+=head1 AUTHOR
+
+Simon Ruderich, E<lt>simon@ruderich.orgE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2012 by Simon Ruderich
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+=head1 SEE ALSO
+
+L<sysconf(3)>, L<pathconf(3)>
+
+=cut