#!/bin/sh # # 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 [optional] # *callback [optional] # Deal with optional -o (output) argument if [ "$1" = "-o" ]; then OUTFILE="$2" shift 2 else OUTFILE=def_data fi if [ $# -gt 0 ]; then INFILE="$1" shift else INFILE=def_data.in fi if [ $# -gt 0 ]; then echo "usage: $0 [-o output] [input_file]" 1>&2 fi ${AWK-awk} -f - -v outfile=$OUTFILE $INFILE <<'EOF' BEGIN { tuple_values[0] = "never" tuple_keys["never"] = 0 ntuples = 1 header = outfile ".h" cfile = outfile ".c" type_map["T_INT"] = "ival" type_map["T_UINT"] = "uival" type_map["T_STR"] = "str" type_map["T_FLAG"] = "flag" type_map["T_MODE"] = "mode" type_map["T_LIST"] = "list" type_map["T_LOGFAC"] = "ival" type_map["T_LOGPRI"] = "ival" type_map["T_TUPLE"] = "tuple" type_map["T_TIMESPEC"] = "tspec" type_map["T_TIMEOUT"] = "ival" type_map["T_RLIMIT"] = "str" } { sub(/#.*/, "", $0) if (/^[[:blank:]]*$/) next if (/^[[:alpha:]]/) { # Store previous record and begin new one if (var) records[count++] = sprintf("%s\n%s\n%s\n%s\n%s\n", var, type, desc, values, callback) var = $1 type = "" desc = "" values = "" callback = "" state = 0 } else { state++ # Strip leading/trailing whitespace gsub(/^[ \t]+|[ \t]+$/, "") if (state == 1) { # type type = $1 } else if (state == 2) { # description if ($0 == "NULL") { desc = "NULL" } else { # Strip leading and trailing double quote and escape the rest gsub(/^"|"$/, "") gsub(/"/, "\\\"") desc = sprintf("N_(\"%s\")", $0) } } else if (state == 3 || state == 4) { if (/^\*/) { callback = substr($0, 2) } else { if (type ~ /^T_TUPLE/) { values = $0 # Add to tuple_values as necessary n = split(values, vals) for (i = 1; i <= n; i++) { if (!(vals[i] in tuple_keys)) { tuple_keys[vals[i]] = ntuples tuple_values[ntuples++] = vals[i] } } } } } else { die("syntax error in input near line " NR) } } } END { if (var) records[count++] = sprintf("%s\n%s\n%s\n%s\n%s\n", var, type, desc, values, callback) print "/* generated file, do not edit */\n" > header print "/* generated file, do not edit */\n" > cfile # Print out value arrays for (i = 0; i < count; i++) { split(records[i], fields, "\n") if (fields[4]) { if (fields[2] !~ /^T_TUPLE/) die("Values list specified for non-tuple " records[1]) printf "static struct def_values def_data_%s[] = {\n", fields[1] > cfile n = split(fields[4], t) for (j = 1; j <= n; j++) { printf " { \"%s\", %s },\n", t[j], t[j] > cfile } print " { NULL, 0 }," > cfile print "};\n" > cfile } } # Print each record print "struct sudo_defs_types sudo_defs_table[] = {\n {" > cfile for (i = 0; i < count; i++) { print_record(records[i], i) } print "\tNULL, 0, NULL\n }\n};" > cfile # Print out def_tuple print "\nenum def_tuple {" > header for (i = 0; i < ntuples; i++) printf "%s %s", i ? ",\n" : "", tuple_values[i] > header print "\n};" > header } function die(msg) { print msg > "/dev/stderr" exit 1 } function print_record(rec, recnum) { split(rec, fields, "\n") type = fields[2] sub(/\|.*/, "", type) if (!(type in type_map)) die("unknown defaults type " fields[2]) # each variable gets a macro to access its value defname = "I_" toupper(fields[1]) printf "#define %-23s %d\n", defname, recnum > header printf "#define def_%-19s (sudo_defs_table[%s].sd_un.%s)\n", fields[1], defname, type_map[type] > header printf "\t\"%s\", %s,\n\t%s,\n", fields[1], fields[2], fields[3] > cfile printf "\t%s,\n", fields[4] ? "def_data_" fields[1] : "NULL" > cfile if (fields[5]) { printf "\t%s,\n", fields[5] > cfile } print " }, {" > cfile } EOF