| #!/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"; | |
| } |