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