1#!/usr/bin/perl -w 2# 3# Generate sudo_defs_table and associated defines 4# 5# Input should be formatted thusly: 6# 7# var_name 8# TYPE 9# description (or NULL) 10# array of struct def_values if TYPE == T_TUPLE 11 12# Deal with optional -o (output) argument 13if ($#ARGV > 0 && $ARGV[0] eq "-o") { 14 shift; 15 $header = $cfile = shift; 16 $header .= '.h'; 17 $cfile .= '.c'; 18} 19die "usage: $0 [input_file]\n" unless $#ARGV == -1 || $#ARGV == 0; 20 21$infile = $ARGV[0] || "def_data.in"; 22if (!defined($header)) { 23 $header = $infile; 24 $header =~ s/(\.in)?$/.h/; 25} 26if (!defined($cfile)) { 27 $cfile = $infile; 28 $cfile =~ s/(\.in)?$/.c/; 29} 30 31open(IN, "<$infile") || die "$0: can't open $infile: $!\n"; 32open(HEADER, ">$header") || die "$0: can't open $header: $!\n"; 33open(CFILE, ">$cfile") || die "$0: can't open $cfile: $!\n"; 34 35$count = 0; 36@tuple_values = ( "never" ); 37@records = (); 38while(<IN>) { 39 chomp; 40 s/\s*#.*$//; 41 next if /^\s*$/; 42 43 if (/^\S/) { 44 # Store previous record and begin new one 45 $records[$count++] = [$var, $type, $desc, $values, $callback] if defined($var); 46 47 $var = $_; 48 $type = ''; 49 $desc = undef; 50 $values = undef; 51 $callback = undef; 52 $field = 0; 53 } else { 54 $field++; 55 s/^\s+//; 56 s/\s+$//; 57 if ($field == 1) { 58 # type 59 $type = $_; 60 } elsif ($field == 2) { 61 # description 62 if ($_ eq "NULL") { 63 $desc = "NULL"; 64 } else { 65 # Strip leading and trailing double quote and escape the rest 66 s/^"//; 67 s/"$//; 68 s/"/\\"/g; 69 $desc = "\"$_\""; 70 } 71 } elsif ($field == 3 || $field == 4) { 72 if (s/^\*//) { 73 $callback = $_; 74 } else { 75 die "$0: syntax error near line $.\n" if $type !~ /^T_TUPLE/; 76 $values = [ split ]; 77 foreach $v (@$values) { 78 push(@tuple_values, $v) unless grep(/^$v$/, @tuple_values); 79 } 80 } 81 } else { 82 die "$0: syntax error near line $.\n"; 83 } 84 } 85} 86$records[$count++] = [$var, $type, $desc, $values, $callback] if defined($var); 87 88# Print out value arrays 89for ($i = 0; $i < $count; $i++) { 90 if (defined($records[$i]->[3])) { 91 die "Values list specified for non-tupple\n" unless 92 $records[$i]->[1] =~ /^T_TUPLE/; 93 printf CFILE "static struct def_values def_data_%s[] = {\n", $records[$i]->[0]; 94 foreach (@{$records[$i]->[3]}) { 95 print CFILE " { \"$_\", $_ },\n"; 96 } 97 print CFILE " { NULL, 0 },\n"; 98 print CFILE "};\n\n"; 99 } 100} 101 102# Print each record 103print CFILE "struct sudo_defs_types sudo_defs_table[] = {\n {\n"; 104for ($i = 0; $i < $count; $i++) { 105 &print_record($records[$i], $i); 106} 107print CFILE "\tNULL, 0, NULL\n }\n};\n"; 108 109# Print out def_tuple 110if (@tuple_values) { 111 print HEADER "\nenum def_tupple {\n"; 112 for ($i = 0; $i <= $#tuple_values; $i++) { 113 printf HEADER "\t%s%s\n", $tuple_values[$i], 114 $i != $#tuple_values ? "," : ""; 115 } 116 print HEADER "};\n"; 117} 118 119close(IN); 120close(HEADER); 121close(CFILE); 122 123sub print_record { 124 my ($rec, $recnum) = @_; 125 my ($i, $v, $defname); 126 # each variable gets a macro to access its value 127 for ($rec->[1]) { 128 if (/^T_U?INT/) { $v = "ival"; } 129 elsif (/^T_STR/) { $v = "str"; } 130 elsif (/^T_FLAG/) { $v = "flag"; } 131 elsif (/^T_MODE/) { $v = "mode"; } 132 elsif (/^T_LIST/) { $v = "list"; } 133 elsif (/^T_LOGFAC/) { $v = "ival"; } 134 elsif (/^T_LOGPRI/) { $v = "ival"; } 135 elsif (/^T_TUPLE/) { $v = "tuple"; } 136 elsif (/^T_FLOAT/) { $v = "fval"; } 137 else { die "$0: unknown defaults type: $_\n"; } 138 } 139 printf HEADER "#define %-23s (sudo_defs_table[$recnum].sd_un.${v})\n", 140 "def_$rec->[0]"; 141 142 $defname = "I_" . uc($rec->[0]); 143 printf HEADER "#define %-24s%d", $defname, $recnum; 144 #print HEADER "\t/* $rec->[2] */" if defined($rec->[2]); 145 print HEADER "\n"; 146 147 print CFILE "\t\"$rec->[0]\", $rec->[1],\n\t$rec->[2],\n"; 148 if (defined($rec->[3])) { 149 printf CFILE "\tdef_data_$rec->[0],\n"; 150 } else { 151 printf CFILE "\tNULL,\n"; 152 } 153 printf CFILE "\t$rec->[4],\n" if defined($rec->[4]); 154 print CFILE " }, {\n"; 155} 156