#!/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 == 0; $infile = $ARGV[0]; 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() { 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"; } else { die "$0: unknown defaults type: $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"; }