exec perl -x -S $0 ${1+"$@"}
if ($] !~ /^5\..*/) {
foreach (split(/:/, $ENV{PATH})) { exec("$_/perl5", "-w", "-x", "-S", $0, @ARGV) if (-x "$_/perl5");
}
die "Your perl is too old; I need perl 5.\n";
}
eval join("\n", <DATA>);
if ($@) { die "$@"; }
__END__
require 5;
use Getopt::Long;
my $opt_extra = undef;
$ret = GetOptions("extra:s");
if (!$ret || $ print STDERR "snmpgen [--extra=trailer.in] app.snmp\n";
exit;
}
$infile = $ARGV[0];
if ($infile =~ m|.*/(.*)\.snmp|) {
$basename = $1;
} elsif ($infile =~ m|(.*)\.snmp|) {
$basename = $1;
} else {
$basename = $infile;
}
print "basename $basename\n";
$outheader = "$basename.h";
$outprog = "$basename.c";
open (INPUT,"<$infile");
my $linenum = 0;
my $found = 0;
my $base = "NOT";
my $num_cmds = 0;
my %T; my %D; my %O;
push @Varlist, "LISTEND";
while (defined ($line = <INPUT>)) {
$linenum++;
if ($line =~ /^ next;
}
if ($line =~ /^\s*$/) {
next;
}
if ($line =~ /^define\s+(\w+)\s+((\d|\.|\[\w+\])+)/)
{
$defname = $1;
$defoid = $2;
while ($defoid =~ /(\[(\w+)\])/)
{
my $f = 0;
foreach my $a (keys %Definelist)
{
if ($a eq $2)
{
$defoid =~ s/\[\w+\]/$Definelist{$a}/;
$f = 1;
}
}
if ($f == 0) {
die "Unable to resolve definition $2";
}
}
$Definelist{$defname} = $defoid;
next;
}
if ($line =~ /^var\s+(\w+)/) {
push @Varlist, $1;
next;
}
if ($line =~ /^BASE\s+((\d+|\.|\{\w+\}|\[\w+\])+)/) {
$base = $1;
while ($base =~ /(\[(\w+)\])/)
{
my $f = 0;
foreach my $a (keys %Definelist)
{
if ($a eq $2)
{
$base =~ s/\[\w+\]/$Definelist{$a}/;
$f = 1;
}
}
if ($f == 0) {
die "Unable to resolve definition $2";
}
}
if ($base =~ /((\d+\.)+\d+)/) {
push @Registerlist, $1;
}
undef @baseVlist;
while ($base =~ /(\{(\w+)\})/)
{
push @baseVlist, $2;
$base =~ s/\{\w+\}/%d/;
}
$basecount = 0;
next;
}
chomp $line;
($type, $name, $desc, $oid, $dummy) = split(/\s*,\s*/, $line, 5);
if (!(defined $oid) || (defined $dummy)) {
die "syntax error on line $linenum\n";
}
if ($oid eq "auto") {
$oid = $base . ".$basecount";
$basecount++;
} else {
$oid = $base . "." . $oid;
}
$T{$name} = $type;
$D{$name} = $desc;
$O{$name} = $oid;
$Ovlist{$name} = [ @baseVlist ];
}
open (OUTPUT_H, ">$outheader");
print OUTPUT_H <<EOF
/* $outheader -- statistics push interface
* generated automatically from $infile by snmpgen
*
* Copyright 2000 Carnegie Mellon University
*
* No warranty, yadda yadda
*/
EOF
;
foreach my $a (keys %Definelist)
{
print OUTPUT_H "#define SNMPDEFINE_$a \"$Definelist{$a}\"\n";
}
print OUTPUT_H <<EOF
typedef void ${basename}_t;
typedef enum {
EOF
;
my $initialized = 0;
foreach my $name (keys %T) {
print OUTPUT_H ",\n" if $initialized;
print OUTPUT_H " $name";
$initialized = 1;
}
print OUTPUT_H <<EOF
} ${basename}_t;
typedef enum {
EOF
;
$initialized = 0;
foreach my $name (@Varlist) {
print OUTPUT_H ",\n" if $initialized;
print OUTPUT_H " VARIABLE_$name";
$initialized = 1;
}
print OUTPUT_H <<EOF
} ${basename}_variable_t;
int snmp_connect(void);
int snmp_close(void);
/* only valid on counters */
int snmp_increment(${basename}_t cmd, int);
int snmp_increment_args(${basename}_t cmd, int incr, ...);
/* only valid on values */
int snmp_set(${basename}_t cmd, int);
int snmp_set_str(${basename}_t cmd, char *value);
int snmp_set_oid(${basename}_t cmd, char *str);
int snmp_set_time(${basename}_t cmd, time_t t);
const char *snmp_getdescription(${basename}_t cmd);
const char *snmp_getoid(const char *name, ${basename}_t cmd, char* buf, int buflen);
void snmp_setvariable(${basename}_variable_t, int);
EOF
;
close OUTPUT_H;
open (OUTPUT_C,">$outprog");
print OUTPUT_C <<EOF
/* $outprog -- automatically generated from $infile by snmpgen */
/* We disable this code for now since it doesn't actually work and wastes
* resources. At some point in time, we'll make it work again as it would
* be useful to gather aggregate statistics on what commands are being used
* so we can better tune the server. This change closes bug * New bug 1267 opened to re-enable the feature.
*/
extern int close(int);
int variable_value[$int variable_tmpvalue[$
int varvalue(${basename}_variable_t var)
{
if (variable_tmpvalue[var]!=-1)
return variable_tmpvalue[var];
return variable_value[var];
}
const char *snmp_getdescription(${basename}_t evt)
{
switch (evt) {
EOF
;
foreach my $a (keys %T)
{
print OUTPUT_C " case $a: return $D{$a};\n";
}
print OUTPUT_C <<EOF
}
return NULL;
}
const char *snmp_getoid(const char *name __attribute__((unused)),
${basename}_t evt, char *buf, int buflen)
{
switch (evt) {
EOF
;
foreach my $a (keys %T)
{
print OUTPUT_C " case $a: snprintf(buf,buflen,\"$O{$a}\"";
foreach my $b (@{ $Ovlist{$a} })
{
print OUTPUT_C ",varvalue(VARIABLE_$b)";
}
print OUTPUT_C "); return buf;\n";
}
$snmp.= " default: return \"0.0.0\";\n";
$snmp.= " }\n";
$snmp.= "}\n";
print OUTPUT_C <<EOF
}
return NULL;
}
static int mysock = -1;
static struct sockaddr_un remote;
static int sockaddr_len = 0;
static void snmp_send(char *str)
{
if (mysock == -1) return;
if (sendto(mysock, str, strlen(str), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) {
return;
}
return;
}
int snmp_connect(void)
{
int s;
int fdflags;
int lup;
if ((s = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
return 1;
}
for (lup=0;lup < $ variable_tmpvalue[lup] = -1;
remote.sun_family = AF_UNIX;
strlcpy(remote.sun_path, SOCK_PATH, sizeof(remote.sun_path));
sockaddr_len = strlen(remote.sun_path) + sizeof(remote.sun_family);
/* put us in non-blocking mode */
fdflags = fcntl(s, F_GETFD, 0);
if (fdflags != -1) fdflags = fcntl(s, F_SETFL, O_NONBLOCK | fdflags);
if (fdflags == -1) { close(s); return -1; }
mysock = s;
EOF
;
foreach my $oid (@Registerlist) {
print OUTPUT_C " snmp_send(\"R $oid\\n\");\n";
}
print OUTPUT_C <<EOF
return 0;
}
int snmp_close(void)
{
if (mysock > -1)
close(mysock);
return 0;
}
int snmp_increment_args(${basename}_t cmd, int incr, ...)
{
char tosend[256]; /* xxx UDP max size??? */
char buf[256];
va_list ap; /* varargs thing */
${basename}_variable_t vval;
int ival;
if (mysock == -1) return 1;
va_start(ap, incr);
do {
vval = va_arg(ap, ${basename}_variable_t); /* get the next arg */
if (vval!=VARIABLE_LISTEND)
{
ival = va_arg(ap, int); /* get the next arg */
variable_tmpvalue[vval] = ival;
}
} while ( vval != VARIABLE_LISTEND);
va_end(ap);
snprintf(tosend, sizeof(tosend),"C %s %d\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), incr);
if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) {
return 1;
}
/* set tmp variables back */
va_start(ap, incr);
do {
vval = va_arg(ap, ${basename}_variable_t); /* get the next arg */
if (vval!=VARIABLE_LISTEND)
{
ival = va_arg(ap, int); /* get the next arg */
variable_tmpvalue[vval] = -1;
}
} while ( vval != VARIABLE_LISTEND);
va_end(ap);
return 0;
}
int snmp_increment(${basename}_t cmd, int incr)
{
char tosend[256]; /* xxx UDP max size??? */
char buf[256];
if (mysock == -1) return 1;
snprintf(tosend, sizeof(tosend),"C %s %d\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), incr);
if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) {
return 1;
}
return 0;
}
int snmp_set(${basename}_t cmd, int value)
{
char tosend[256];
char buf[256];
if (mysock == -1) return 1;
snprintf(tosend, sizeof(tosend),"I %s %d\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), value);
if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) {
return 1;
}
return 1;
}
int snmp_set_str(${basename}_t cmd, char *value)
{
char tosend[256];
char buf[256];
if (mysock == -1) return 1;
snprintf(tosend, sizeof(tosend),"S %s %s\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), value);
if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) {
return 1;
}
return 1;
}
int snmp_set_time(${basename}_t cmd, time_t t)
{
char tosend[256];
char buf[256];
if (mysock == -1) return 1;
snprintf(tosend, sizeof(tosend),"T %s %lu\\n",snmp_getoid(NULL,cmd,buf,sizeof(buf)), t);
if (sendto(mysock, tosend, strlen(tosend), 0, (struct sockaddr *) &remote, sockaddr_len) == -1) {
return 1;
}
return 1;
}
/* should use SNMPDEFINE's as parameter */
int snmp_set_oid(${basename}_t cmd, char *str)
{
return snmp_set_str(cmd,str);
}
void snmp_setvariable(${basename}_variable_t name, int value)
{
variable_value[name] = value;
}
#endif
EOF
;
if (defined $opt_extra) {
open (INPUT_IN,"<$opt_extra");
while( <INPUT_IN> )
{
print OUTPUT_C;
}
close INPUT_IN;
}
close OUTPUT_C;