blob: 90f3b0cb8c4f6dc53ea5ae5c5301cd2ccf571e9b [file] [log] [blame]
#!/usr/bin/perl -w
#
# 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
# 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";
$count = 0;
@tuple_values = ( "never" );
@records = ();
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 = "\"$_\"";
}
} elsif ($field == 3 || $field == 4) {
if (s/^\*//) {
$callback = $_;
} else {
die "$0: syntax error near line $.\n" if $type !~ /^T_TUPLE/;
$values = [ split ];
foreach $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 ($i = 0; $i < $count; $i++) {
if (defined($records[$i]->[3])) {
die "Values list specified for non-tupple\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 ($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_tupple {\n";
for ($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);
sub print_record {
my ($rec, $recnum) = @_;
my ($i, $v, $defname);
# each variable gets a macro to access its value
for ($rec->[1]) {
if (/^T_U?INT/) { $v = "ival"; }
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_FLOAT/) { $v = "fval"; }
else { die "$0: unknown defaults type: $_\n"; }
}
printf HEADER "#define %-23s (sudo_defs_table[$recnum].sd_un.${v})\n",
"def_$rec->[0]";
$defname = "I_" . uc($rec->[0]);
printf HEADER "#define %-24s%d", $defname, $recnum;
#print HEADER "\t/* $rec->[2] */" if defined($rec->[2]);
print HEADER "\n";
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";
}