--- /dev/null
+#!/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