]> ruderich.org/simon Gitweb - config/dotfiles.git/blob - shell/bin/print-constant.pl
shell/dircolors: support README.adoc
[config/dotfiles.git] / shell / bin / print-constant.pl
1 #!/usr/bin/perl
2
3 # Print values of C constants.
4
5 # Copyright (C) 2012  Simon Ruderich
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21 use strict;
22 use warnings;
23
24 use Getopt::Long ();
25 use File::Temp ();
26
27 our $VERSION = '0.01';
28
29
30 my $option_help     = 0;
31 my $option_version  = 0;
32 my @option_include  = ();
33 my $option_pathconf = undef;
34 my $option_quiet    = 0;
35 my $option_sysconf  = 0;
36 my $option_type     = 'd';
37 if (not Getopt::Long::GetOptions(
38             'help|h|?'     => \$option_help,
39             'version|v'    => \$option_version,
40             #
41             'include|i=s'  => \@option_include,
42             'pathconf|p=s' => \$option_pathconf,
43             'quiet|q'      => \$option_quiet,
44             'sysconf|s'    => \$option_sysconf,
45             'type|t=s'     => \$option_type,
46         )) {
47     require Pod::Usage;
48     Pod::Usage::pod2usage(2);
49 }
50 if ($option_help) {
51     require Pod::Usage;
52     Pod::Usage::pod2usage(1);
53 }
54 if ($option_version) {
55     print <<EOF;
56 print-constant $VERSION  Copyright (C) 2012  Simon Ruderich
57
58 This program is free software: you can redistribute it and/or modify
59 it under the terms of the GNU General Public License as published by
60 the Free Software Foundation, either version 3 of the License, or
61 (at your option) any later version.
62
63 This program is distributed in the hope that it will be useful,
64 but WITHOUT ANY WARRANTY; without even the implied warranty of
65 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
66 GNU General Public License for more details.
67
68 You should have received a copy of the GNU General Public License
69 along with this program.  If not, see <http://www.gnu.org/licenses/>.
70 EOF
71     exit 0;
72 }
73
74 # We need the constant name as argument.
75 if (scalar @ARGV != 1) {
76     require Pod::Usage;
77     Pod::Usage::pod2usage(2);
78 }
79
80
81 my $constant = $ARGV[0];
82 # Check for non-constant name inputs - also prevents running arbitrary code on
83 # the machine.
84 if (not $constant =~ /^[a-zA-Z0-9_]+$/) {
85     print STDERR "Invalid constant name: '$constant'!\n";
86     exit 1;
87 }
88
89 # Some sanity checks.
90 if (not $option_type =~ /^[a-zA-Z]+$/) {
91     print STDERR "Invalid type: '$option_type'!\n";
92     exit 1;
93 }
94 if ($option_sysconf and defined $option_pathconf) {
95     print STDERR "--sysconf and --pathconf can't be used together!\n";
96     exit 1;
97 }
98 foreach my $include (@option_include) {
99     if (not $include =~ m{^[a-zA-Z0-9./_-]+$}) {
100         print STDERR "Invalid include: '$include'!\n";
101         exit 1;
102     }
103 }
104
105 my $constant_display = $constant;
106 # Pass the constant to sysconf()/pathconf() instead of using it directly.
107 if ($option_sysconf) {
108     $constant = "sysconf($constant)";
109     $constant_display = $constant;
110 } elsif (defined $option_pathconf) {
111     $constant_display = "pathconf(\"$option_pathconf\", $constant)";
112     # Use the current directory to prevent escape problems for the path, see
113     # below.
114     $constant = "pathconf(\".\", $constant)";
115 }
116
117
118 # Use "limits.h" and "unistd.h" as default include - but only if the user
119 # specified no other includes, in case it conflicts with "limits.h".
120 if (scalar @option_include == 0) {
121     push @option_include, 'limits.h';
122     push @option_include, 'unistd.h';
123 }
124
125
126 # Temporary directory where the following C program which prints the constant
127 # is built.
128 my $tempdir = File::Temp::tempdir(CLEANUP => 1) or die $!;
129 chdir $tempdir or die $!;
130
131 # Write the C file which prints the constant value.
132 my $c_template = <<'EOF';
133 #include <stdio.h>
134 #include <stdlib.h>
135 %s
136
137 int main(int argc, char **argv) {
138     printf("%s\n", %s);
139
140     return EXIT_SUCCESS;
141 }
142 EOF
143 open my $fh, '>', 'constant.c' or die $!;
144 printf $fh $c_template,
145            join("\n", map { "#include <$_>" } @option_include),
146            '%' . $option_type,
147            $constant;
148 close $fh or die $!;
149
150 # Compile the constant C file.
151 my @args = ('cc', '-o', 'constant', 'constant.c');
152 if (system(@args) != 0) {
153     print STDERR "Compilation failure (message above).\n";
154
155     chdir; # see below
156     exit 1;
157 }
158
159 # pathconf() needs a path, we use the current directory - therefore we have to
160 # chdir to the given path. This prevents escape problems with the path.
161 if (defined $option_pathconf) {
162     chdir $option_pathconf;
163 }
164
165 my $value = `$tempdir/constant`;
166
167 if ($option_quiet) {
168     print $value;
169 } else {
170     print "$constant_display: $value";
171 }
172
173 # Change the working directory or File::Temp can't remove our temporary
174 # directory.
175 chdir;
176
177
178 __END__
179
180 =head1 NAME
181
182 print-constant - print values of C constants
183
184 =head1 SYNOPSIS
185
186 B<print-constant> [I<options>] I<CONSTANT_NAME>
187
188 =head1 DESCRIPTION
189
190 print-constant prints the values of C constants. Useful to find out certain
191 system constants without having to write a small C program to print them.
192
193 =head1 OPTIONS
194
195 =over 8
196
197 =item B<-i> I<include>, B<--include> I<include>
198
199 Use I<include> as include file. Adds C<#include E<lt>includeE<gt>> to the
200 beginning of the C file used to print the constant. By default C<limits.h> and
201 C<unistd.h> are used as headers. If this option is specified I<no> default
202 includes are used. Can be specified multiple times.
203
204 =item B<-p> I<path>, B<--pathconf> I<path>
205
206 Pass the constant to pathconf(3) and print the result. I<path> is the first
207 argument for pathconf(3). Conflicts with B<--sysconf>.
208
209 =item B<-q>, B<--quiet>
210
211 Display only the constant's value.
212
213 =item B<-s>, B<--sysconf>
214
215 Pass the constant to sysconf(3) and print the result. Conflicts with
216 B<--pathconf>.
217
218 =item B<-t> I<type>, B<--type> I<type>
219
220 Use I<type> as type of the constant, used in printf(3). By default C<d> is
221 used.
222
223 =item B<-h>, B<-?>, B<--help>
224
225 Print available options.
226
227 =item B<-v>, B<--version>
228
229 Print version number and license.
230
231 =back
232
233 =head1 AUTHOR
234
235 Simon Ruderich, E<lt>simon@ruderich.orgE<gt>
236
237 =head1 COPYRIGHT AND LICENSE
238
239 Copyright (C) 2012 by Simon Ruderich
240
241 This program is free software: you can redistribute it and/or modify
242 it under the terms of the GNU General Public License as published by
243 the Free Software Foundation, either version 3 of the License, or
244 (at your option) any later version.
245
246 This program is distributed in the hope that it will be useful,
247 but WITHOUT ANY WARRANTY; without even the implied warranty of
248 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
249 GNU General Public License for more details.
250
251 You should have received a copy of the GNU General Public License
252 along with this program.  If not, see <http://www.gnu.org/licenses/>.
253
254 =head1 SEE ALSO
255
256 L<sysconf(3)>, L<pathconf(3)>
257
258 =cut