diff options
Diffstat (limited to 'plugins/sudoers/mkdefaults')
-rwxr-xr-x | plugins/sudoers/mkdefaults | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/plugins/sudoers/mkdefaults b/plugins/sudoers/mkdefaults new file mode 100755 index 0000000..885c1b5 --- /dev/null +++ b/plugins/sudoers/mkdefaults @@ -0,0 +1,164 @@ +#!/usr/bin/env perl +# +# Generate sudo_defs_table and associated defines +# +# Input should be formatted thusly: +# +# var_name +# TYPE +# description (or NULL) +# array of struct def_values if TYPE == T_TUPLE + +use warnings; +use strict; + +my ($header, $cfile, $infile); + +# Deal with optional -o (output) argument +if ($#ARGV > 0 && $ARGV[0] eq "-o") { + shift; + $header = $cfile = shift; + $header .= '.h'; + $cfile .= '.c'; +} +die "usage: $0 [input_file]\n" unless $#ARGV == -1 || $#ARGV == 0; + +$infile = $ARGV[0] || "def_data.in"; +if (!defined($header)) { + $header = $infile; + $header =~ s/(\.in)?$/.h/; +} +if (!defined($cfile)) { + $cfile = $infile; + $cfile =~ s/(\.in)?$/.c/; +} + +open(IN, "<$infile") || die "$0: can't open $infile: $!\n"; +open(HEADER, ">$header") || die "$0: can't open $header: $!\n"; +open(CFILE, ">$cfile") || die "$0: can't open $cfile: $!\n"; + +my $count = 0; +my @tuple_values = ( "never" ); +my @records = (); +my ($var, $type, $desc, $values, $callback, $field); +while (<IN>) { + chomp; + s/\s*#.*$//; + next if /^\s*$/; + + if (/^\S/) { + # Store previous record and begin new one + $records[$count++] = [$var, $type, $desc, $values, $callback] if defined($var); + + $var = $_; + $type = ''; + $desc = undef; + $values = undef; + $callback = undef; + $field = 0; + } else { + $field++; + s/^\s+//; + s/\s+$//; + if ($field == 1) { + # type + $type = $_; + } elsif ($field == 2) { + # description + if ($_ eq "NULL") { + $desc = "NULL"; + } else { + # Strip leading and trailing double quote and escape the rest + s/^"//; + s/"$//; + s/"/\\"/g; + $desc = "N_(\"$_\")"; + } + } elsif ($field == 3 || $field == 4) { + if (s/^\*//) { + $callback = $_; + } else { + die "$0: syntax error near line $.\n" if $type !~ /^T_TUPLE/; + $values = [ split ]; + foreach my $v (@$values) { + push(@tuple_values, $v) unless grep(/^$v$/, @tuple_values); + } + } + } else { + die "$0: syntax error near line $.\n"; + } + } +} +$records[$count++] = [$var, $type, $desc, $values, $callback] if defined($var); + +# Print out value arrays +for (my $i = 0; $i < $count; $i++) { + if (defined($records[$i]->[3])) { + die "Values list specified for non-tuple\n" unless + $records[$i]->[1] =~ /^T_TUPLE/; + printf CFILE "static struct def_values def_data_%s[] = {\n", + $records[$i]->[0]; + foreach (@{$records[$i]->[3]}) { + print CFILE " { \"$_\", $_ },\n"; + } + print CFILE " { NULL, 0 },\n"; + print CFILE "};\n\n"; + } +} + +# Print each record +print CFILE "struct sudo_defs_types sudo_defs_table[] = {\n {\n"; +for (my $i = 0; $i < $count; $i++) { + print_record($records[$i], $i); +} +print CFILE "\tNULL, 0, NULL\n }\n};\n"; + +# Print out def_tuple +if (@tuple_values) { + print HEADER "\nenum def_tuple {\n"; + for (my $i = 0; $i <= $#tuple_values; $i++) { + printf HEADER "\t%s%s\n", $tuple_values[$i], + $i != $#tuple_values ? "," : ""; + } + print HEADER "};\n"; +} + +close(IN); +close(HEADER); +close(CFILE); + +exit(0); + +sub print_record { + my ($rec, $recnum) = @_; + my ($i, $v, $defname); + + # each variable gets a macro to access its value + $defname = "I_" . uc($rec->[0]); + printf HEADER "#define %-23s %d\n", $defname, $recnum; + for ($rec->[1]) { + if (/^T_INT/) { $v = "ival"; } + elsif (/^T_UINT/) { $v = "uival"; } + elsif (/^T_STR/) { $v = "str"; } + elsif (/^T_FLAG/) { $v = "flag"; } + elsif (/^T_MODE/) { $v = "mode"; } + elsif (/^T_LIST/) { $v = "list"; } + elsif (/^T_LOGFAC/) { $v = "ival"; } + elsif (/^T_LOGPRI/) { $v = "ival"; } + elsif (/^T_TUPLE/) { $v = "tuple"; } + elsif (/^T_TIMESPEC/) { $v = "tspec"; } + elsif (/^T_TIMEOUT/) { $v = "ival"; } + else { die "$0: unknown defaults type: $_\n"; } + } + printf HEADER "#define %-23s (sudo_defs_table[$defname].sd_un.${v})\n", + "def_$rec->[0]"; + + print CFILE "\t\"$rec->[0]\", $rec->[1],\n\t$rec->[2],\n"; + if (defined($rec->[3])) { + printf CFILE "\tdef_data_$rec->[0],\n"; + } else { + printf CFILE "\tNULL,\n"; + } + printf CFILE "\t$rec->[4],\n" if defined($rec->[4]); + print CFILE " }, {\n"; +} |