From f9a416743401121e1bc2961402cd6f87de68ca00 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 3 Oct 2005 23:27:33 +0000 Subject: r10694: Add some work I did this afternoon on getting pidl to output Samba3 RPC parsers. Currently the following files can be generated: - include/rpc_BASENAME.h - rpc_server/srv_BASENAME.c - rpc_server/srv_BASENAME_nt.c (template only, user has to fill in functions) - rpc_client/cli_BASENAME.c - rpc_parse/parse_BASENAME.c So far, I have been working on getting DFS working. Currently still to do (all in rpc_parse/parse_BASENAME.c): - Proper handling of declarations - Proper handling of scalar/buffer parts of structs and unions - Subcontexts - Proper handling of arrays - Support for custom (non-scalar) types I hope to have a somewhat more working version later this week. Some files as currently generated are available from: http://samba.org/~jelmer/pidl_samba3/ (This used to be commit 8af8eaeeef6d46f4d25ccb1d25890e1eef063e4f) --- source4/pidl/lib/Parse/Pidl/Ethereal/NDR.pm | 6 +- source4/pidl/lib/Parse/Pidl/NDR.pm | 33 ++- source4/pidl/lib/Parse/Pidl/Samba3/Client.pm | 104 ++++++++++ source4/pidl/lib/Parse/Pidl/Samba3/Header.pm | 160 +++++++++++++++ source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm | 269 +++++++++++++++++++++++++ source4/pidl/lib/Parse/Pidl/Samba3/Server.pm | 115 +++++++++++ source4/pidl/lib/Parse/Pidl/Samba3/Template.pm | 66 ++++++ source4/pidl/lib/Parse/Pidl/Samba3/Util.pm | 29 +++ source4/pidl/lib/Parse/Pidl/Typelist.pm | 38 +--- source4/pidl/pidl | 78 ++++++- 10 files changed, 856 insertions(+), 42 deletions(-) create mode 100644 source4/pidl/lib/Parse/Pidl/Samba3/Client.pm create mode 100644 source4/pidl/lib/Parse/Pidl/Samba3/Header.pm create mode 100644 source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm create mode 100644 source4/pidl/lib/Parse/Pidl/Samba3/Server.pm create mode 100644 source4/pidl/lib/Parse/Pidl/Samba3/Template.pm create mode 100644 source4/pidl/lib/Parse/Pidl/Samba3/Util.pm diff --git a/source4/pidl/lib/Parse/Pidl/Ethereal/NDR.pm b/source4/pidl/lib/Parse/Pidl/Ethereal/NDR.pm index 8441ea25b9..b497f87403 100644 --- a/source4/pidl/lib/Parse/Pidl/Ethereal/NDR.pm +++ b/source4/pidl/lib/Parse/Pidl/Ethereal/NDR.pm @@ -485,6 +485,8 @@ sub Union($$$) $res.="\t\tbreak;\n"; } + my $switch_type = $e->{SWITCH_TYPE}; + pidl_code "static int"; pidl_code "$dissectorname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)"; pidl_code "{"; @@ -492,7 +494,7 @@ sub Union($$$) pidl_code "proto_item *item = NULL;"; pidl_code "proto_tree *tree = NULL;"; pidl_code "int old_offset;"; - pidl_code "g$e->{SWITCH_TYPE} level;"; + pidl_code "g$switch_type level;"; pidl_code ""; if ($e->{ALIGN} > 1) { @@ -511,7 +513,7 @@ sub Union($$$) pidl_code ""; - pidl_code "offset = dissect_ndr_$e->{SWITCH_TYPE}(tvb, offset, pinfo, tree, drep, hf_index, &level);"; + pidl_code "offset = dissect_ndr_$switch_type(tvb, offset, pinfo, tree, drep, hf_index, &level);"; pidl_code "switch(level) {$res\t}"; pidl_code "proto_item_set_len(item, offset-old_offset);\n"; diff --git a/source4/pidl/lib/Parse/Pidl/NDR.pm b/source4/pidl/lib/Parse/Pidl/NDR.pm index 42c9fd133b..6bb92a3b50 100644 --- a/source4/pidl/lib/Parse/Pidl/NDR.pm +++ b/source4/pidl/lib/Parse/Pidl/NDR.pm @@ -17,6 +17,37 @@ use strict; use Parse::Pidl::Typelist qw(hasType getType); use Parse::Pidl::Util qw(has_property property_matches); +# Alignment of the built-in scalar types +my $scalar_alignment = { + 'void' => 0, + 'char' => 1, + 'int8' => 1, + 'uint8' => 1, + 'int16' => 2, + 'uint16' => 2, + 'int32' => 4, + 'uint32' => 4, + 'hyper' => 8, + 'dlong' => 4, + 'udlong' => 4, + 'udlongr' => 4, + 'DATA_BLOB' => 4, + 'string' => 4, + 'string_array' => 4, #??? + 'time_t' => 4, + 'NTTIME' => 4, + 'NTTIME_1sec' => 4, + 'NTTIME_hyper' => 8, + 'WERROR' => 4, + 'NTSTATUS' => 4, + 'COMRESULT' => 4, + 'nbt_string' => 4, + 'wrepl_nbt_name' => 4, + 'ipv4address' => 4 +}; + + + sub nonfatal($$) { my ($e,$s) = @_; @@ -299,7 +330,7 @@ sub align_type } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) { return find_largest_alignment($dt); } elsif ($dt->{TYPE} eq "SCALAR") { - return Parse::Pidl::Typelist::getScalarAlignment($dt->{NAME}); + return $scalar_alignment->{$dt->{NAME}}; } die("Unknown data type type $dt->{TYPE}"); diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Client.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Client.pm new file mode 100644 index 0000000000..59d048176f --- /dev/null +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Client.pm @@ -0,0 +1,104 @@ +################################################### +# Samba3 NDR client generator for IDL structures +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba3::Client; + +use strict; +use Parse::Pidl::Typelist qw(hasType getType mapType); +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); +use Parse::Pidl::Samba3::Util qw(MapSamba3Type); + +use vars qw($VERSION); +$VERSION = '0.01'; + +my $res = ""; +my $tabs = ""; +sub indent() { $tabs.="\t"; } +sub deindent() { $tabs = substr($tabs, 1); } +sub pidl($) { $res .= $tabs.(shift)."\n"; } +sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); } + +sub ParseFunction($$) +{ + my ($if,$fn) = @_; + + my $args = ""; + my $defargs = ""; + foreach (@{$fn->{ELEMENTS}}) { + $defargs .= ", " . MapSamba3Type($_); + $args .= ", $_->{NAME}"; + } + + my $uif = uc($if->{NAME}); + my $ufn = uc($fn->{NAME}); + + pidl "NTSTATUS rpccli_$fn->{NAME}(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx$defargs)"; + pidl "{"; + indent; + pidl "prs_struct qbuf, rbuf;"; + pidl "$uif\_Q_$ufn q;"; + pidl "$uif\_R_$ufn r;"; + pidl ""; + pidl "ZERO_STRUCT(q);"; + pidl "ZERO_STRUCT(r);"; + pidl ""; + pidl "/* Marshall data and send request */"; + pidl ""; + pidl "init_$if->{NAME}_q_$fn->{NAME}(&q$args);"; + pidl ""; + pidl "CLI_DO_RPC(cli, mem_ctx, PI_$uif, $ufn,"; + pidl "\tq, r,"; + pidl "\tqbuf, rbuf, "; + pidl "\t$if->{NAME}_q_$fn->{NAME},"; + pidl "\t$if->{NAME}_r_$fn->{NAME},"; + pidl "\tNT_STATUS_UNSUCCESSFUL);"; + pidl ""; + pidl "/* Return result */"; + if (not $fn->{RETURN_TYPE}) { + pidl "return NT_STATUS_OK;"; + } elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") { + pidl "return r.status;"; + } elsif ($fn->{RETURN_TYPE} eq "WERROR") { + pidl "return werror_to_ntstatus(r.status);"; + } else { + pidl "/* Sorry, don't know how to convert $fn->{RETURN_TYPE} to NTSTATUS */"; + pidl "return NT_STATUS_OK;"; + } + + deindent; + pidl "}"; + pidl ""; +} + +sub ParseInterface($) +{ + my $if = shift; + + ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}}); +} + +sub Parse($$) +{ + my($ndr,$filename) = @_; + + $res = ""; + + pidl "/*"; + pidl " * Unix SMB/CIFS implementation."; + pidl " * client auto-generated by pidl. DO NOT MODIFY!"; + pidl " */"; + pidl ""; + pidl "#include \"includes.h\""; + pidl ""; + + foreach (@$ndr) { + ParseInterface($_) if ($_->{TYPE} eq "INTERFACE"); + } + + return $res; +} + +1; diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm new file mode 100644 index 0000000000..be7f1ca5c4 --- /dev/null +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Header.pm @@ -0,0 +1,160 @@ +################################################### +# Samba3 NDR header generator for IDL structures +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba3::Header; + +use strict; +use Parse::Pidl::Typelist qw(hasType getType); +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); +use Parse::Pidl::Samba3::Util qw(MapSamba3Type); + +use vars qw($VERSION); +$VERSION = '0.01'; + +my $res = ""; +sub pidl($) { my $x = shift; $res .= "$x\n"; } +sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); } + +sub CreateStruct($$$$) +{ + my ($if,$fn,$n,$t) = @_; + + pidl "typedef struct $n {"; + foreach my $e (@$t) { + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER") { + return if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "top"); + pidl "\tuint32 ptr_$e->{NAME};"; + } elsif ($l->{TYPE} eq "SWITCH") { + pidl "\tuint32 level_$e->{NAME};"; + } elsif ($l->{TYPE} eq "DATA") { + pidl "\t" . MapSamba3Type($e) . ";"; + } + } + } + + if (not @$t) { + # Some compilers don't like empty structs + pidl "\tuint32 dummy;"; + } + + pidl "} " . uc($n) . ";"; + pidl ""; +} + +sub ParseFunction($$) +{ + my ($if,$fn) = @_; + + my @in = (); + my @out = (); + + foreach (@{$_->{ELEMENTS}}) { + push (@in, $_) if (grep(/in/, @{$_->{DIRECTION}})); + push (@out, $_) if (grep(/out/, @{$_->{DIRECTION}})); + } + + if (defined($fn->{RETURN_TYPE})) { + push (@out, { + NAME => "status", + TYPE => $fn->{RETURN_TYPE}, + LEVELS => [ + { + TYPE => "DATA", + DATA_TYPE => $fn->{RETURN_TYPE} + } + ] + } ); + } + + # define Q + R structures for functions + + CreateStruct($if, $fn, "$if->{NAME}_q_$fn->{NAME}", \@in); + CreateStruct($if, $fn, "$if->{NAME}_r_$fn->{NAME}", \@out); +} + +sub ParseStruct($$$) +{ + my ($if,$s,$n) = @_; + + CreateStruct($if, $s, "$if->{NAME}_$n", $s->{ELEMENTS}); +} + +sub ParseEnum($$$) +{ + my ($if,$s,$n) = @_; + + pidl "typedef enum {"; + + foreach (@{$s->{ELEMENTS}}) { + pidl "$_,"; + } + + pidl "} $n;"; +} + +sub ParseBitmap($$$) +{ + my ($if,$s,$n) = @_; + + pidl "#define $_" foreach (@{$s->{ELEMENTS}}); +} + +sub ParseInterface($) +{ + my $if = shift; + + my $def = "_RPC_" . uc($if->{NAME}) . "_H"; + + pidl ""; + + pidl "\#ifndef $def"; + pidl "\#define $def"; + + pidl ""; + + foreach (@{$if->{FUNCTIONS}}) { + pidl "\#define " . uc($_->{NAME}) . " $_->{OPNUM}" ; + } + + pidl ""; + + ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}}); + + foreach (@{$if->{TYPEDEFS}}) { + ParseStruct($if, $_->{DATA}, $_->{NAME}) if ($_->{TYPE} eq "STRUCT"); + ParseEnum($if, $_->{DATA}, $_->{NAME}) if ($_->{TYPE} eq "ENUM"); + ParseBitmap($if, $_->{DATA}, $_->{NAME}) if ($_->{TYPE} eq "BITMAP"); + fatal($_, "Unions not supported for Samba3 yet") if ($_->{TYPE} eq "STRUCT"); + } + + foreach (@{$if->{CONSTS}}) { + pidl "$_->{NAME} ($_->{VALUE})"; + } + + pidl "\#endif /* $def */"; +} + +sub Parse($$) +{ + my($ndr,$filename) = @_; + + $res = ""; + + pidl "/*"; + pidl " * Unix SMB/CIFS implementation."; + pidl " * header auto-generated by pidl. DO NOT MODIFY!"; + pidl " */"; + pidl ""; + + # Loop over interfaces + foreach (@{$ndr}) { + ParseInterface($_) if ($_->{TYPE} eq "INTERFACE"); + } + return $res; +} + +1; diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm new file mode 100644 index 0000000000..8518537ddb --- /dev/null +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm @@ -0,0 +1,269 @@ +################################################### +# Samba3 NDR parser generator for IDL structures +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba3::Parser; + +use strict; +use Parse::Pidl::Typelist qw(hasType getType mapType); +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); +use Parse::Pidl::Samba3::Util qw(MapSamba3Type); + +use vars qw($VERSION); +$VERSION = '0.01'; + +my $res = ""; +my $tabs = ""; +sub indent() { $tabs.="\t"; } +sub deindent() { $tabs = substr($tabs, 1); } +sub pidl($) { $res .= $tabs.(shift)."\n"; } +sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); } + +sub ParseElementLevelData($$$$$) +{ + my ($e,$l,$nl,$env,$varname) = @_; + + #FIXME: This only works for scalar types + pidl "if (!prs_$l->{DATA_TYPE}(\"$e->{NAME}\", ps, depth, &$varname))"; + pidl "\treturn False;"; + pidl ""; +} + +sub ParseElementLevelArray($$$$$) +{ + my ($e,$l,$nl,$env,$varname) = @_; + + #FIXME + pidl "for (i=0; i<".ParseExpr("length_$e->{NAME}", $env) .";i++) {"; + indent; + ParseElementLevel($e,$nl,$env,"$varname\[i]"); + deindent; + pidl "}"; +} + +sub ParseElementLevelSwitch($$$$$) +{ + my ($e,$l,$nl,$env,$varname) = @_; + + pidl "if (!prs_uint32(\"level\", ps, depth, " . ParseExpr("level_$e->{NAME}", $env) . ", ps, depth))"; + pidl "\treturn False;"; + pidl ""; + + ParseElementLevel($e,$nl,$env,$varname); +} + +sub ParseElementLevelPtr($$$$$) +{ + my ($e,$l,$nl,$env,$varname) = @_; + + # No top-level ref pointers for Samba 3 + return if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP"); + + pidl "if (!prs_uint32(\"ptr_$e->{NAME}\",ps,depth,&" . ParseExpr("ptr_$e->{NAME}", $env) . ", ps, depth))"; + pidl "\treturn False;"; + pidl ""; + + pidl "if (" . ParseExpr("ptr_$e->{NAME}", $env) . ") {"; + indent; + ParseElementLevel($e,$nl,$env,$varname); + deindent; + pidl "}"; +} + +sub ParseElementLevelSubcontext($$$$$) +{ + my ($e,$l,$nl,$env,$varname) = @_; + + fatal($e, "subcontext() not supported for Samba 3"); +} + +sub ParseElementLevel($$$$) +{ + my ($e,$l,$env,$varname) = @_; + + { + DATA => \&ParseElementLevelData, + SUBCONTEXT => \&ParseElementLevelSubcontext, + POINTER => \&ParseElementLevelPtr, + SWITCH => \&ParseElementLevelSwitch, + ARRAY => \&ParseElementLevelArray + }->{$l->{TYPE}}->($e,$l,GetNextLevel($e,$l),$env,$varname); +} + +sub ParseElement($$) +{ + my ($e,$env) = @_; + + ParseElementLevel($e, $e->{LEVELS}[0], $env, ParseExpr($e->{NAME}, $env)); +} + +sub CreateStruct($$$) +{ + my ($fn,$s,$es) = @_; + + my $args = ""; + foreach my $e (@$es) { + $args .= ", " . MapSamba3Type($_); + } + + pidl "BOOL init_$fn($s *v$args)"; + pidl "{"; + indent; + pidl "DEBUG(5,(\"init_$fn\\n\"));"; + # Call init for all arguments + foreach my $e (@$es) { + foreach my $l (@{$e->{LEVELS}}) { + #FIXME + } + } + pidl "return True;"; + deindent; + pidl "}"; + pidl ""; + + pidl "BOOL $fn(const char *desc, $s *v, prs_struct *ps, int depth)"; + pidl "{"; + indent; + pidl "if (v == NULL)"; + pidl "\treturn False;"; + pidl ""; + pidl "prs_debug(ps, depth, desc, \"$fn\");"; + pidl "depth++;"; + pidl "if (!prs_align(ps))"; + pidl "\treturn False;"; + pidl ""; + + my $env = {}; + foreach my $e (@$es) { + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "DATA") { + $env->{"$e->{NAME}"} = $e->{"v->$e->{NAME}"}; + } elsif ($l->{TYPE} eq "POINTER") { + $env->{"ptr_$e->{NAME}"} = $e->{"v->ptr_$e->{NAME}"}; + } elsif ($l->{TYPE} eq "SWITCH") { + $env->{"level_$e->{NAME}"} = $e->{"v->level_$e->{NAME}"}; + } + } + } + + ParseElement($_, $env) foreach (@$es); + + pidl "return True;"; + deindent; + pidl "}"; + pidl ""; +} + +sub ParseStruct($$$) +{ + my ($if,$s,$n) = @_; + + my $fn = "$if->{NAME}_io_$n"; + my $sn = uc("$if->{NAME}_$n"); + + CreateStruct($fn, $sn, $s->{ELEMENTS}); +} + +sub ParseUnion($$$) +{ + my ($if,$u,$n) = @_; + + my $fn = "$if->{NAME}_io_$n"; + my $sn = uc("$if->{NAME}_$n"); + + pidl "BOOL $fn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)"; + pidl "{"; + indent; + pidl "switch (level) {"; + indent; + + foreach (@{$u->{ELEMENTS}}) { + pidl "$_->{CASE}:"; + indent; + pidl "depth++;"; + ParseElement($_, {}); + deindent; + pidl "depth--;"; + pidl "break"; + } + + deindent; + pidl "}"; + pidl ""; + pidl "return True;"; + deindent; + pidl "}"; +} + +sub ParseFunction($$) +{ + my ($if,$fn) = @_; + + my @in = (); + my @out = (); + + foreach (@{$fn->{ELEMENTS}}) { + push (@in, $_) if (grep(/in/, @{$_->{DIRECTION}})); + push (@out, $_) if (grep(/out/, @{$_->{DIRECTION}})); + } + + if (defined($fn->{RETURN_TYPE})) { + push (@out, { + NAME => "status", + TYPE => $fn->{RETURN_TYPE}, + LEVELS => [ + { + TYPE => "DATA", + DATA_TYPE => $fn->{RETURN_TYPE} + } + ] + } ); + } + + CreateStruct("$if->{NAME}_io_q_$fn->{NAME}", uc("$if->{NAME}_q_$fn->{NAME}"), \@in); + CreateStruct("$if->{NAME}_io_r_$fn->{NAME}", uc("$if->{NAME}_r_$fn->{NAME}"), \@out); +} + +sub ParseInterface($) +{ + my $if = shift; + + # Structures first + pidl "/* $if->{NAME} structures */"; + foreach (@{$if->{TYPEDEFS}}) { + ParseStruct($if, $_->{DATA}, $_->{NAME}) if ($_->{TYPE} eq "STRUCT"); + ParseUnion($if, $_->{DATA}, $_->{NAME}) if ($_->{TYPE} eq "UNION"); + } + + pidl "/* $if->{NAME} functions */"; + ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}}); +} + +sub Parse($$) +{ + my($ndr,$filename) = @_; + + $tabs = ""; + $res = ""; + + pidl "/*"; + pidl " * Unix SMB/CIFS implementation."; + pidl " * parser auto-generated by pidl. DO NOT MODIFY!"; + pidl " */"; + pidl ""; + pidl "#include \"includes.h\""; + pidl ""; + pidl "#undef DBGC_CLASS"; + pidl "#define DBGC_CLASS DBGC_RPC_PARSE"; + pidl ""; + + foreach (@$ndr) { + ParseInterface($_) if ($_->{TYPE} eq "INTERFACE"); + } + + return $res; +} + +1; diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Server.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Server.pm new file mode 100644 index 0000000000..0372cf1117 --- /dev/null +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Server.pm @@ -0,0 +1,115 @@ +################################################### +# Samba3 NDR server generator for IDL structures +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba3::Server; + +use strict; +use Parse::Pidl::Typelist qw(hasType getType mapType); +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); + +my $res = ""; +my $tabs = ""; + +sub indent() { $tabs.="\t"; } +sub deindent() { $tabs = substr($tabs, 1); } +sub pidl($) { $res .= $tabs.(shift)."\n"; } + +use vars qw($VERSION); +$VERSION = '0.01'; + +sub ParseFunction($$) +{ + my ($if,$fn) = @_; + + pidl "/******************************************************************"; + pidl " api_$fn->{NAME}"; + pidl " *****************************************************************/"; + pidl ""; + pidl "static BOOL api_$fn->{NAME}(pipes_struct *p)"; + pidl "{"; + indent; + pidl uc("$if->{NAME}_q_$fn->{NAME}") . " q_u;"; + pidl uc("$if->{NAME}_r_$fn->{NAME}") . " r_u;"; + pidl "prs_struct *data = &p->in_data.data"; + pidl "prs_struct *rdata = &p->out_data.rdata"; + pidl ""; + pidl "if (!$if->{NAME}_io_q_$fn->{NAME}(\"\", &q_u, data, 0))"; + pidl "\treturn False;"; + pidl ""; + pidl "r_u.status = _$fn->{NAME}(p, &q_u, &r_u);"; + pidl ""; + pidl "if (!$if->{NAME}_io_r_$fn->{NAME}(\"\", &r_u, rdata, 0))"; + pidl "\treturn False;"; + pidl ""; + pidl "return True;"; + deindent; + pidl "}"; +} + +sub ParseInterface($) +{ + my $if = shift; + + ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}}); + + pidl ""; + pidl "/* Tables */"; + pidl "static struct api_struct api_$if->{NAME}_cmds[] = "; + pidl "{"; + indent; + foreach (@{$if->{FUNCTIONS}}) { + pidl "{\"" . uc($_->{NAME}) . "\", " . uc($_->{NAME}) . ", api_$_->{NAME}},"; + } + deindent; + pidl "};"; + + pidl ""; + + pidl "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns)"; + pidl "{"; + indent; + pidl "*fns = api_$if->{NAME}_cmds;"; + pidl "*n_fns = sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct);"; + deindent; + pidl "}"; + + pidl ""; + + pidl "NTSTATUS rpc_$if->{NAME}_init(void)"; + pidl "{"; + indent; + pidl "return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct));"; + deindent; + pidl "}"; +} + +sub Parse($$) +{ + my($ndr,$filename) = @_; + + $tabs = ""; + $res = ""; + + pidl "/*"; + pidl " * Unix SMB/CIFS implementation."; + pidl " * server auto-generated by pidl. DO NOT MODIFY!"; + pidl " */"; + pidl ""; + pidl "#include \"includes.h\""; + pidl "#include \"nterr.h\""; + pidl ""; + pidl "#undef DBGC_CLASS"; + pidl "#define DBGC_CLASS DBGC_RPC"; + pidl ""; + + foreach (@$ndr) { + ParseInterface($_) if ($_->{TYPE} eq "INTERFACE"); + } + + return $res; +} + +1; diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Template.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Template.pm new file mode 100644 index 0000000000..072aa07850 --- /dev/null +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Template.pm @@ -0,0 +1,66 @@ +################################################### +# Samba3 NDR client generator for IDL structures +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba3::Template; + +use strict; +use Parse::Pidl::Typelist qw(hasType getType mapType); +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); + +use vars qw($VERSION); +$VERSION = '0.01'; + +my $res; +sub pidl($) { my $x = shift; $res.="$x\n"; } + +sub ParseInterface($) +{ + my $if = shift; + + foreach (@{$if->{FUNCTIONS}}) { + my $ret = $_->{RETURN_TYPE}; + if (not $ret) { $ret = "void"; } + pidl "$ret _$_->{NAME}(pipes_struct *p, " . uc($if->{NAME}) . "_Q_" . uc($_->{NAME}) . " *q_u, " . uc($if->{NAME}) . "_R_" . uc($_->{NAME}) . " *r_u)"; + pidl "{"; + pidl "\t/* FIXME: Implement your code here */"; + if (not defined($_->{RETURN_TYPE})) { + } elsif ($_->{RETURN_TYPE} eq "WERROR") { + pidl "\treturn WERR_NOT_SUPPORTED;"; + } elsif ($_->{RETURN_TYPE} eq "NTSTATUS") { + pidl "\treturn NT_STATUS_NOT_IMPLEMENTED;"; + } elsif ($_->{RETURN_TYPE} eq "uint32") { + pidl "\treturn 0;"; + } + pidl "}"; + pidl ""; + } +} + +sub Parse($$) +{ + my($ndr,$filename) = @_; + + $res = ""; + + pidl "/*"; + pidl " * Unix SMB/CIFS implementation."; + pidl " * template auto-generated by pidl. Modify to your needs"; + pidl " */"; + pidl ""; + pidl "#include \"includes.h\""; + pidl ""; + pidl "#undef DBGC_CLASS"; + pidl "#define DBGC_CLASS DBGC_MSRPC"; + pidl ""; + + foreach (@$ndr) { + ParseInterface($_) if ($_->{TYPE} eq "INTERFACE"); + } + + return $res; +} + +1; diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Util.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Util.pm new file mode 100644 index 0000000000..2d4179df76 --- /dev/null +++ b/source4/pidl/lib/Parse/Pidl/Samba3/Util.pm @@ -0,0 +1,29 @@ +################################################### +# Samba3 common helper functions +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba3::Util; + +require Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw(MapSamba3Type); + +use strict; +use Parse::Pidl::Typelist qw(hasType getType mapType); +use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); + +use vars qw($VERSION); +$VERSION = '0.01'; + +sub MapSamba3Type($) +{ + my $e = shift; + + return "UNISTR2 $e->{NAME}" if ($e->{TYPE} eq "string"); + + return "$e->{TYPE} $e->{NAME}"; +} + +1; diff --git a/source4/pidl/lib/Parse/Pidl/Typelist.pm b/source4/pidl/lib/Parse/Pidl/Typelist.pm index d81fedf71e..111ce9ba11 100644 --- a/source4/pidl/lib/Parse/Pidl/Typelist.pm +++ b/source4/pidl/lib/Parse/Pidl/Typelist.pm @@ -7,7 +7,7 @@ package Parse::Pidl::Typelist; require Exporter; @ISA = qw(Exporter); -@EXPORT = qw(hasType getType mapType); +@EXPORT_OK = qw(hasType getType mapType); use vars qw($VERSION); $VERSION = '0.01'; @@ -22,109 +22,90 @@ my $scalars = { "void" => { C_TYPE => "void", IS_REFERENCE => 0, - NDR_ALIGN => 0 }, # 1 byte types "char" => { C_TYPE => "char", IS_REFERENCE => 0, - NDR_ALIGN => 1 }, "int8" => { C_TYPE => "int8_t", IS_REFERENCE => 0, - NDR_ALIGN => 1 }, "uint8" => { C_TYPE => "uint8_t", IS_REFERENCE => 0, - NDR_ALIGN => 1 }, # 2 byte types "int16" => { C_TYPE => "int16_t", IS_REFERENCE => 0, - NDR_ALIGN => 2 }, "uint16" => { C_TYPE => "uint16_t", IS_REFERENCE => 0, - NDR_ALIGN => 2 }, # 4 byte types "int32" => { C_TYPE => "int32_t", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "uint32" => { C_TYPE => "uint32_t", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, # 8 byte types "hyper" => { C_TYPE => "uint64_t", IS_REFERENCE => 0, - NDR_ALIGN => 8 }, "dlong" => { C_TYPE => "int64_t", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "udlong" => { C_TYPE => "uint64_t", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "udlongr" => { C_TYPE => "uint64_t", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, # DATA_BLOB types "DATA_BLOB" => { C_TYPE => "DATA_BLOB", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, # string types "string" => { C_TYPE => "const char *", IS_REFERENCE => 1, - NDR_ALIGN => 4 #??? }, "string_array" => { C_TYPE => "const char **", IS_REFERENCE => 1, - NDR_ALIGN => 4 #??? }, # time types "time_t" => { C_TYPE => "time_t", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "NTTIME" => { C_TYPE => "NTTIME", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "NTTIME_1sec" => { C_TYPE => "NTTIME", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "NTTIME_hyper" => { C_TYPE => "NTTIME", IS_REFERENCE => 0, - NDR_ALIGN => 8 }, @@ -132,34 +113,28 @@ my $scalars = { "WERROR" => { C_TYPE => "WERROR", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "NTSTATUS" => { C_TYPE => "NTSTATUS", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "COMRESULT" => { C_TYPE => "COMRESULT", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, # special types "nbt_string" => { C_TYPE => "const char *", IS_REFERENCE => 1, - NDR_ALIGN => 4 #??? }, "wrepl_nbt_name"=> { C_TYPE => "struct nbt_name", IS_REFERENCE => 0, - NDR_ALIGN => 4 }, "ipv4address" => { C_TYPE => "const char *", IS_REFERENCE => 1, - NDR_ALIGN => 4 } }; @@ -175,17 +150,6 @@ sub mapScalarType($) die("Unknown scalar type $name"); } -sub getScalarAlignment($) -{ - my $name = shift; - - # it's a bug when a type is not in the list - # of known scalars or has no mapping - return $scalars->{$name}{NDR_ALIGN} if defined($scalars->{$name}) and defined($scalars->{$name}{NDR_ALIGN}); - - die("Unknown scalar type $name"); -} - sub addType($) { my $t = shift; diff --git a/source4/pidl/pidl b/source4/pidl/pidl index 01de049a6c..f0513546e9 100755 --- a/source4/pidl/pidl +++ b/source4/pidl/pidl @@ -15,7 +15,7 @@ pidl - IDL Compiler written in Perl =head1 SYNOPSIS pidl --help -pidl [--outputdir[=OUTNAME]] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--ndr-header[=OUTPUT]] [--header[=OUTPUT]] [--ejs[=OUTPUT]] [--swig[=OUTPUT]] [--uint-enums] [--ndr-parser[=OUTPUT]] [--client] [--server] [--dcom-proxy] [--com-header] [--warn-compat] [--quiet] [--verbose] [--template] [--eth-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-header=[OUTPUT]] [--tdr-parser[=OUTPUT]] [.idl]... +pidl [--outputdir[=OUTNAME]] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--ndr-header[=OUTPUT]] [--header[=OUTPUT]] [--ejs[=OUTPUT]] [--swig[=OUTPUT]] [--uint-enums] [--ndr-parser[=OUTPUT]] [--client] [--server] [--dcom-proxy] [--com-header] [--warn-compat] [--quiet] [--verbose] [--template] [--eth-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-header=[OUTPUT]] [--tdr-parser[=OUTPUT]] [--samba3-header[=OUTPUT]] [--samba3-parser=[OUTPUT]] [--samba3-server=[OUTPUT]] [--samba3-template[=OUTPUT]] [--samba3-client[=OUTPUT]] [.idl]... =head1 DESCRIPTION @@ -114,6 +114,30 @@ file the to disk. Useful for debugging pidl. Tell pidl to dump the internal NDR information tree it generated from the IDL file to disk. Useful for debugging pidl. +=item I<--samba3-header> + +Generate Samba3-style RPC header file. Filename defaults to rpc_BASENAME.h. + +=item I<--samba3-parser> + +Generate parser file for Samba3, to be placed in rpc_parse/. Filename defaults +to parse_BASENAME.c. + +=item I<--samba3-server> + +Generate server file for Samba3, to be placed in rpc_server/. Filename defaults +to srv_BASENAME.c. + +=item I<--samba3-template> + +Generate template for server-side implementation in Samba3, to be placed in +rpc_server/. Filename defaults to srv_BASENAME_nt.c + +=item I<--samba3-client> + +Generate client calls for Samba 3, to be placed in rpc_client/. Filename +defaults to cli_BASENAME.c. + =back =head1 IDL SYNTAX @@ -486,6 +510,11 @@ my($opt_uint_enums) = 0; my($opt_diff) = 0; my($opt_header); my($opt_ndr_header); +my($opt_samba3_header); +my($opt_samba3_parser); +my($opt_samba3_server); +my($opt_samba3_template); +my($opt_samba3_client); my($opt_template) = 0; my($opt_client); my($opt_server); @@ -540,6 +569,13 @@ Samba 4 output: --dcom-proxy[=OUTFILE] create DCOM proxy [ndr_BASENAME_p.c] --com-header[=OUTFILE] create header for COM [com_BASENAME.h] +Samba 3 output: + --samba3-header[=OUTF] create Samba3-style header [rpc_BASENAME.h] + --samba3-parser[=OUTF] create parser for Samba3 [parse_BASENAME.c] + --samba3-template[=OUTF]create template implementation [srv_BASENAME_nt.c] + --samba3-server[=OUTF] create server side wrappers for Samba3 [srv_BASENAME.c] + --samba3-client[=OUTF] create client calls for Samba3 [cli_BASENAME.c] + Ethereal parsers: --eth-parser[=OUTFILE] create ethereal parser and header \n"; @@ -556,6 +592,11 @@ my $result = GetOptions ( 'dump-ndr-tree:s' => \$opt_dump_ndr_tree, 'uint-enums' => \$opt_uint_enums, 'ndr-header:s' => \$opt_ndr_header, + 'samba3-header:s' => \$opt_samba3_header, + 'samba3-parser:s' => \$opt_samba3_parser, + 'samba3-server:s' => \$opt_samba3_server, + 'samba3-template:s' => \$opt_samba3_template, + 'samba3-client:s' => \$opt_samba3_client, 'header:s' => \$opt_header, 'server:s' => \$opt_server, 'tdr-header:s' => \$opt_tdr_header, @@ -662,7 +703,9 @@ sub process_file($) if (defined($opt_ndr_header) or defined($opt_eth_parser) or defined($opt_client) or defined($opt_server) or defined($opt_ndr_parser) or defined($opt_ejs) or - defined($opt_dump_ndr_tree)) { + defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or + defined($opt_samba3_header) or defined($opt_samba3_server) or + defined($opt_samba3_template) or defined($opt_samba3_client)) { require Parse::Pidl::NDR; Parse::Pidl::NDR::Validate($pidl); $ndr = Parse::Pidl::NDR::Parse($pidl); @@ -769,6 +812,37 @@ $dcom require Parse::Pidl::Samba::Template; print Parse::Pidl::Samba::Template::Parse($pidl); } + + if (defined($opt_samba3_header)) { + my $header = ($opt_samba3_header or "$outputdir/rpc_$basename.h"); + require Parse::Pidl::Samba3::Header; + FileSave($header, Parse::Pidl::Samba3::Header::Parse($ndr, $basename)); + } + + if (defined($opt_samba3_parser)) { + my $header = ($opt_samba3_parser or "$outputdir/parse_$basename.c"); + require Parse::Pidl::Samba3::Parser; + FileSave($header, Parse::Pidl::Samba3::Parser::Parse($ndr, $basename)); + } + + if (defined($opt_samba3_server)) { + my $header = ($opt_samba3_server or "$outputdir/srv_$basename.c"); + require Parse::Pidl::Samba3::Server; + FileSave($header, Parse::Pidl::Samba3::Server::Parse($ndr, $basename)); + } + + if (defined($opt_samba3_template)) { + my $header = ($opt_samba3_template or "$outputdir/srv_$basename\_nt.c"); + require Parse::Pidl::Samba3::Template; + FileSave($header, Parse::Pidl::Samba3::Template::Parse($ndr, $basename)); + } + + if (defined($opt_samba3_client)) { + my $header = ($opt_samba3_client or "$outputdir/cli_$basename.c"); + require Parse::Pidl::Samba3::Client; + FileSave($header, Parse::Pidl::Samba3::Client::Parse($ndr, $basename)); + } + } if (scalar(@ARGV) == 0) { -- cgit