7befe1588754450dec8cf149df4abcfab4ff3a57
[debian/sudo] / plugins / sudoers / mkdefaults
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
13 if ($#ARGV > 0 && $ARGV[0] eq "-o") {
14     shift;
15     $header = $cfile = shift;
16     $header .= '.h';
17     $cfile .= '.c';
18 }
19 die "usage: $0 [input_file]\n" unless $#ARGV == -1 || $#ARGV == 0;
20
21 $infile = $ARGV[0] || "def_data.in";
22 if (!defined($header)) {
23     $header = $infile;
24     $header =~ s/(\.in)?$/.h/;
25 }
26 if (!defined($cfile)) {
27     $cfile = $infile;
28     $cfile =~ s/(\.in)?$/.c/;
29 }
30
31 open(IN, "<$infile") || die "$0: can't open $infile: $!\n";
32 open(HEADER, ">$header") || die "$0: can't open $header: $!\n";
33 open(CFILE, ">$cfile") || die "$0: can't open $cfile: $!\n";
34
35 $count = 0;
36 @tuple_values = ( "never" );
37 @records = ();
38 while(<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
89 for ($i = 0; $i < $count; $i++) {
90     if (defined($records[$i]->[3])) {
91         die "Values list specified for non-tuple\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
103 print CFILE "struct sudo_defs_types sudo_defs_table[] = {\n    {\n";
104 for ($i = 0; $i < $count; $i++) {
105     &print_record($records[$i], $i);
106 }
107 print CFILE "\tNULL, 0, NULL\n    }\n};\n";
108
109 # Print out def_tuple
110 if (@tuple_values) {
111     print HEADER "\nenum def_tuple {\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
119 close(IN);
120 close(HEADER);
121 close(CFILE);
122
123 sub 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 }