diff --git a/backends/server/.cvsignore b/backends/server/.cvsignore new file mode 100644 index 00000000..a081b16a --- /dev/null +++ b/backends/server/.cvsignore @@ -0,0 +1,7 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.la +marshal.c diff --git a/backends/server/ChangeLog b/backends/server/ChangeLog new file mode 100644 index 00000000..b875f1b4 --- /dev/null +++ b/backends/server/ChangeLog @@ -0,0 +1,12 @@ +2000-01-01 Martin Baulig + + Initial version of the "glibtop-backend-server" backend. + + * command.c, read.c, read_data.c, write.c: New files. Moved here + from the `lib' directory. + + * backend-server.c: New file. + * glibtop-backend-private.h: New file. + + * marshal.pl: New file. Automatically creates `marshal.c'. + diff --git a/backends/server/Makefile.am b/backends/server/Makefile.am new file mode 100644 index 00000000..5781eb14 --- /dev/null +++ b/backends/server/Makefile.am @@ -0,0 +1,30 @@ +LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@ + +INCLUDES = @INCLUDES@ + +noinst_HEADERS = \ + glibtop-backend-private.h + +lib_LTLIBRARIES = \ + libgtop_backend_server.la + +libgtop_backend_server_la_SOURCES = \ + backend-server.c \ + marshal.c \ + command.c \ + read.c \ + read_data.c \ + write.c + +libgtop_backend_server_la_LDFLAGS = \ + $(LT_VERSION_INFO) + +BUILT_SOURCES = \ + marshal.c + +CLEANFILES = $(BUILT_SOURCES) + +marshal.c: marshal.pl $(top_builddir)/config.h $(top_srcdir)/features.def $(top_srcdir)/scripts/c_types.pl + $(PERL) -I $(top_srcdir)/scripts $(srcdir)/marshal.pl < $(top_srcdir)/features.def > tmp-t + mv tmp-t marshal.c + diff --git a/backends/server/backend-server.c b/backends/server/backend-server.c new file mode 100644 index 00000000..addf427c --- /dev/null +++ b/backends/server/backend-server.c @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig , April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include + +#include +#include + +static int +_open_server (glibtop *, glibtop_backend *, u_int64_t, const char **); + +static int +_close_server (glibtop *, glibtop_backend *); + +extern glibtop_call_vector glibtop_backend_server_call_vector; + +glibtop_backend_info glibtop_backend_server = { + "glibtop-backend-server", _open_server, _close_server, + &glibtop_backend_server_call_vector +}; + +static int +_open_server (glibtop *server, glibtop_backend *backend, + u_int64_t features, const char **backend_args) +{ + backend->_priv = glibtop_calloc_r + (server, 1, sizeof (glibtop_backend_private)); + + fprintf (stderr, "open_server - %p, %p, %p\n", server, backend, + backend->_priv); + + fprintf (stderr, "Opening pipe to server (%s).\n", + LIBGTOP_SERVER); + + if (pipe (backend->_priv->input) || + pipe (backend->_priv->output)) { + glibtop_warn_io_r (server, "cannot make a pipe"); + return -1; + } + + backend->_priv->pid = fork (); + + if (backend->_priv->pid < 0) { + glibtop_warn_io_r (server, "fork failed"); + return -1; + } else if (backend->_priv->pid == 0) { + close (0); close (1); + close (backend->_priv->input [0]); + close (backend->_priv->output [1]); + dup2 (backend->_priv->input [1], 1); + dup2 (backend->_priv->output [0], 0); + execl (LIBGTOP_SERVER, "libgtop-server", NULL); + glibtop_error_io_r (server, "execl (%s)", + LIBGTOP_SERVER); + _exit (2); + } + + close (backend->_priv->input [1]); + close (backend->_priv->output [0]); + + return 0; +} + +static int +_close_server (glibtop *server, glibtop_backend *backend) +{ + kill (backend->_priv->pid, SIGKILL); + close (backend->_priv->input [0]); + close (backend->_priv->output [1]); + + backend->_priv->pid = 0; + + return 0; +} + diff --git a/backends/server/command.c b/backends/server/command.c new file mode 100644 index 00000000..5bbdc75f --- /dev/null +++ b/backends/server/command.c @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig , April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include + +#include +#include + +void * +glibtop_call_l (glibtop *server, unsigned command, size_t send_size, + const void *send_buf, size_t recv_size, void *recv_buf, + int *retval_ptr) +{ + glibtop_command cmnd; + glibtop_response response; + int retval; + + glibtop_init_r (&server, 0, 0); + + memset (&cmnd, 0, sizeof (glibtop_command)); + + cmnd.command = command; + + /* If send_size is less than _GLIBTOP_PARAM_SIZE (normally 16 Bytes), we + * send it together with command, so we only need one system call instead + * of two. */ + + if (send_size <= _GLIBTOP_PARAM_SIZE) { + memcpy (cmnd.parameter, send_buf, send_size); + cmnd.size = send_size; + } else { + cmnd.data_size = send_size; + } + + glibtop_write_l (server, sizeof (glibtop_command), &cmnd); + + glibtop_read_l (server, sizeof (glibtop_response), &response); + +#ifdef DEBUG + fprintf (stderr, "RESPONSE: %lu - %d\n", + response.offset, response.data_size); +#endif + + glibtop_read_l (server, sizeof (int), &retval); + if (retval_ptr) + *retval_ptr = retval; + + if (recv_buf) + memcpy (recv_buf, ((char *) &response) + response.offset, + recv_size); + + if (response.data_size) { + void *ptr = glibtop_malloc_r (server, response.data_size); + + glibtop_read_l (server, response.data_size, ptr); + + return ptr; + } + + return NULL; +} diff --git a/backends/server/glibtop-backend-private.h b/backends/server/glibtop-backend-private.h new file mode 100644 index 00000000..1861a456 --- /dev/null +++ b/backends/server/glibtop-backend-private.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig , April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GLIBTOP_BACKEND_PRIVATE_H__ +#define __GLIBTOP_BACKEND_PRIVATE_H__ + +struct _glibtop_backend_private +{ + u_int64_t flags; + int input [2]; /* Pipe client <- server */ + int output [2]; /* Pipe client -> server */ + pid_t pid; /* PID of the server */ +}; + +void +glibtop_read_i (glibtop *server, glibtop_backend *backend, + size_t size, void *buf); + +void * +glibtop_read_data_i (glibtop *server, glibtop_backend *backend); + +void +glibtop_write_i (glibtop *server, glibtop_backend *backend, + size_t size, void *buf); + +#endif diff --git a/backends/server/marshal.pl b/backends/server/marshal.pl new file mode 100644 index 00000000..ada7e320 --- /dev/null +++ b/backends/server/marshal.pl @@ -0,0 +1,250 @@ +#!/usr/bin/perl + +require 'c_types.pl'; + +$[ = 1; # set array base to 1 +$, = ' '; # set output field separator +$\ = "\n"; # set output record separator + +$always_use_temp_storage = 1; + +sub toupper { + local($_) = @_; + tr/a-z/A-Z/; + return $_; +} + +sub tolower { + local($_) = @_; + tr/A-Z/a-z/; + return $_; +} + +print '/* marshal.c */'; +print "/* This is a generated file. Please modify `marshal.pl' */"; +print ''; + +print '#include '; +print '#include '; +print '#include '; +print ''; +print '#include '; +print '#include '; +print ''; +print '#include '; +print '#include '; +print ''; + +$feature_count = 0; + +while (<>) { + chop; # strip record separator + + if (/^[^#]/) { + &output($_); + } +} + +sub output { + local($line) = @_; + @line_fields = split(/\|/, $line, 9999); + $retval = $line_fields[1]; + $feature = $line_fields[2]; + $param_def = $line_fields[4]; + + $orig = $feature; + $feature =~ s/^@//; + $space = $feature; + $space =~ s/./ /g; + + $features{++$feature_count} = $feature; + + if ($retval eq 'retval') { + $retval_param = '&retval'; + $call_prefix = ''; + $call_prefix_space = ''; + $prefix = 'retval = '; + $prefix_space = ' '; + $retval = 'int'; + } + elsif ($retval !~ /^void$/) { + $retval_param = 'NULL'; + $prefix = 'retval = '; + $prefix_space = ' '; + $call_prefix = 'retval = '; + $call_prefix_space = ' '; + } + else { + $retval_param = 'NULL'; + $call_prefix = ''; + $call_prefix_space = ''; + $prefix = ''; + $prefix_space = ''; + } + + if ($retval =~ /^(array|pointer)\((.*)\)$/) { + $retval = ($2 eq 'string') ? 'char **' : "$2 *"; + } + + $need_temp_storage = $always_use_temp_storage; + $size_code = "\t_LIBGTOP_SEND_len = 0;\n"; + $marshal_code = "\t_LIBGTOP_SEND_offset = 0;\n"; + $marshal_code .= "\tmemset (_LIBGTOP_SEND_buf, 0, _LIBGTOP_SEND_len);\n"; + $first_param_name = ''; + + $call_param = ''; + $param_decl = ''; + $need_temp_len = 0; + $nr_params = (@params = split(/:/, $param_def, 9999)); + for ($param = 1; $param <= $nr_params; $param++) { + $list = $params[$param]; + $type = $params[$param]; + $type =~ s/\(.*//; + $list =~ s/^.*\(//; + $list =~ s/\)$//; + $count = (@fields = split(/,/, $list, 9999)); + for ($field = 1; $field <= $count; $field++) { + my $c_type = $typeinfo->{$type}->[1]; + + if ($first_param_name eq '') { + $first_param_name = $fields[$field]; + } + + if ($typeinfo->{$type}->[2]) { + $need_temp_storage = 1; + } + + if ($param_decl eq '') { + $param_decl = ",\n " . $space . ' '; + } + else { + $param_decl = $param_decl . ', '; + } + $param_decl = $param_decl . $c_type . ' ' . $fields[$field]; + $call_param = $call_param . ', ' . $fields[$field]; + + $size_code .= "\t_LIBGTOP_SEND_len += "; + if (defined $sizeof_funcs->{$type}) { + $size_code .= $sizeof_funcs->{$type}->($fields[$field]); + } else { + $size_code .= sprintf ("sizeof (%s)", $c_type); + } + $size_code .= ";\n"; + + $marshal_code .= "\t_LIBGTOP_SEND_ptr = ". + "(char *) _LIBGTOP_SEND_buf + _LIBGTOP_SEND_offset;\n"; + + if (defined $marshal_funcs->{$type}) { + $marshal_code .= $marshal_funcs->{$type}->($c_type, $fields[$field], "\t"); + } else { + $marshal_code .= sprintf ("\tmemcpy (_LIBGTOP_SEND_ptr, %s, %s);\n", + '&'.$fields[$field], "sizeof ($c_type)"); + } + + $marshal_code .= "\t_LIBGTOP_SEND_offset += "; + if (defined $sizeof_funcs->{$type}) { + $marshal_code .= $sizeof_funcs->{$type}->($fields[$field]); + } else { + $marshal_code .= sprintf ("sizeof (%s)", $c_type); + } + $marshal_code .= ";\n"; + } + } + + $local_var_code = ""; + $local_var_code .= "\tunsigned _LIBGTOP_SEND_offset, _LIBGTOP_SEND_len;\n"; + if ($need_temp_len) { + $local_var_code .= "\tunsigned _LIBGTOP_SEND_temp_len;\n"; + } + $local_var_code .= "\tvoid *_LIBGTOP_SEND_buf;\n"; + $local_var_code .= "\tchar *_LIBGTOP_SEND_ptr;\n"; + if ($retval !~ /^void$/) { + $local_var_code .= sprintf ("\t%s retval = (%s) 0;\n", + $retval, $retval); + } + + $total_code = ''; + + $send_buf_code = "\t_LIBGTOP_SEND_buf = "; + if ($need_temp_storage) { + $send_buf_code .= "glibtop_malloc_r (server, _LIBGTOP_SEND_len+1)"; + } else { + $send_buf_code .= '(void *) &'.$first_param_name; + } + $send_buf_code .= ";\n"; + + $call_code = ''; + $call_code .= sprintf ("\t%sglibtop_call_l (server, GLIBTOP_CMND_%s,\n", + $call_prefix, &toupper($feature)); + $call_code .= sprintf ("\t\t\t%s%s, %s,\n", $call_prefix_space, + "_LIBGTOP_SEND_len", "_LIBGTOP_SEND_ptr"); + if ($line_fields[3] eq '') { + $call_code .= sprintf ("\t\t\t%s0, NULL,\n", $call_prefix_space); + } elsif ($line_fields[3] eq 'array') { + $call_code .= sprintf ("\t\t\t%ssizeof (glibtop_array), array,\n", + $call_prefix_space); + } else { + $call_code .= sprintf ("\t\t\t%ssizeof (glibtop_%s), buf,\n", + $call_prefix_space, $feature); + } + $call_code .= sprintf ("\t\t\t%s%s);\n", $call_prefix_space, $retval_param); + + if ($need_temp_storage) { + $send_buf_free_code = "\tglibtop_free_r (server, _LIBGTOP_SEND_buf);\n"; + } else { + $send_buf_free_code = ""; + } + + $total_code .= sprintf ("%s\n%s\n%s\n%s\n%s\n", + $size_code, $send_buf_code, $marshal_code, + $call_code, $send_buf_free_code); + + $return_code = ''; + if ($retval !~ /^void$/) { + $return_code .= "\treturn retval;\n"; + } else { + $return_code .= "\treturn;\n"; + } + + $total_code .= $return_code; + + $func_decl = 'static '.$retval."\n"; + if ($line_fields[3] eq '') { + $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop *server%s)\n", + $feature, $param_decl); + } elsif ($line_fields[3] eq 'array') { + $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop *server, glibtop_array *array%s)\n", + $feature, $param_decl); + } elsif ($line_fields[3] =~ /^array/) { + $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop *server, glibtop_array *array, %s *buf%s)\n", + $feature, 'glibtop_'.$feature, $param_decl); + } else { + $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop *server, %s *buf%s)\n", + $feature, 'glibtop_'.$feature, $param_decl); + } + + $total_code = sprintf ("%s{\n%s\n%s\n%s}\n", $func_decl, + $local_var_code, $total_code); + + + $total_code = sprintf ("#if GLIBTOP_SUID_%s\n\n%s\n#endif /* GLIBTOP_SUID_%s */\n\n", + &toupper($feature), $total_code, + &toupper($feature)); + + print $total_code; +} + +$call_vector_code = ''; +for ($nr = 1; $nr <= $feature_count; $nr++) { + $feature = $features{$nr}; + + $call_vector_code .= sprintf + (qq[\#if GLIBTOP_SUID_%s\n\t_glibtop_get_%s_c,\n\#else\n\tNULL,\n\#endif\n], + &toupper($feature), $feature); +} + +print 'glibtop_call_vector glibtop_backend_server_call_vector = {'; +print $call_vector_code; +print '};'; +print ''; + diff --git a/backends/server/read.c b/backends/server/read.c new file mode 100644 index 00000000..44c9a406 --- /dev/null +++ b/backends/server/read.c @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig , April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include + +#include + +#ifndef DEBUG +#define DEBUG 1 +#endif + +void +glibtop_read_i (glibtop *server, glibtop_backend *backend, + size_t size, void *buf) +{ + int ret = 0; + + glibtop_init_r (&server, 0, 0); + +#ifdef DEBUG + fprintf (stderr, "LIBRARY: really reading %d bytes.\n", size); +#endif + + ret = read (backend->_priv->input [0], buf, size); + + if (ret < 0) + glibtop_error_io_r (server, _("read %d bytes"), size); +} diff --git a/backends/server/read_data.c b/backends/server/read_data.c new file mode 100644 index 00000000..2807ff17 --- /dev/null +++ b/backends/server/read_data.c @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig , April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include + +#include + +#ifndef DEBUG +#define DEBUG 1 +#endif + +void * +glibtop_read_data_i (glibtop *server, glibtop_backend *backend) +{ + size_t size; + void *ptr; + int ret; + +#ifdef DEBUG + fprintf (stderr, "LIBRARY: reading %d data bytes.\n", sizeof (size_t)); +#endif + + ret = read (backend->_priv->input [0], (void *)&size, + sizeof (size_t)); + + if (ret < 0) + glibtop_error_io_r (server, _("read data size")); + +#ifdef DEBUG + fprintf (stderr, "LIBRARY: really reading %d data bytes (ret = %d).\n", size, ret); +#endif + + if (!size) return NULL; + + ptr = glibtop_malloc_r (server, size); + + ret = read (backend->_priv->input [0], ptr, size); + + if (ret < 0) + glibtop_error_io_r (server, _("read data %d bytes")); + + return ptr; +} diff --git a/backends/server/write.c b/backends/server/write.c new file mode 100644 index 00000000..653d5a55 --- /dev/null +++ b/backends/server/write.c @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig , April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include + +#include + +#ifndef DEBUG +#define DEBUG 1 +#endif + +void +glibtop_write_i (glibtop *server, glibtop_backend *backend, + size_t size, void *buf) +{ + int ret; + + if (size == 0) return; + +#ifdef DEBUG + fprintf (stderr, "LIBRARY: really writing %d bytes.\n", size); +#endif + + ret = write (backend->_priv->output [1], buf, size); + + if (ret < 0) + glibtop_error_io_r (server, _("write %d bytes"), size); +}