aboutsummaryrefslogtreecommitdiffstats
path: root/makewrappers
diff options
context:
space:
mode:
Diffstat (limited to 'makewrappers')
-rwxr-xr-xmakewrappers429
1 files changed, 429 insertions, 0 deletions
diff --git a/makewrappers b/makewrappers
new file mode 100755
index 0000000..11ef407
--- /dev/null
+++ b/makewrappers
@@ -0,0 +1,429 @@
+#!/bin/sh
+#
+# makewrappers, script to auto-generate wrapper functions
+#
+# Copyright (c) 2008-2010 Wind River Systems, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the Lesser GNU General Public License version 2.1 as
+# published by the Free Software Foundation.
+#
+# This program 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 Lesser GNU General Public License for more details.
+#
+# You should have received a copy of the Lesser GNU General Public License
+# version 2.1 along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+case $# in
+0) echo >&2 "Usage: makewrappers file [...]"
+ exit 1
+ ;;
+esac
+
+# save old versions
+test -f "pseudo_wrappers.c" && mv pseudo_wrappers.c pseudo_wrappers.c.old
+test -f "pseudo_wrappers.h" && mv pseudo_wrappers.h pseudo_wrappers.h.old
+
+# create files
+exec 5>pseudo_wrappers.c
+exec 6>pseudo_wrappers.h
+exec 7>pseudo_wrapper_table.c
+
+# "cat >&N <<EOF" populates the file on &N with the here-document.
+
+# pseudo_wrappers.c has to have all the hunks used by the wrapper functions,
+# including guts/*.c.
+cat >&5 <<EOF
+`cat guts/COPYRIGHT`
+/* wrapper functions. generated automatically. */
+
+/* This file is generated and should not be modified. See the makewrappers
+ * script if you want to modify this. */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+
+#include "pseudo.h"
+#include "pseudo_wrappers.h"
+#include "pseudo_ipc.h"
+#include "pseudo_client.h"
+
+static void pseudo_enosys(const char *);
+static int pseudo_populate_wrappers(void);
+static volatile int antimagic = 0;
+static pthread_mutex_t pseudo_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t pseudo_mutex_holder;
+static int pseudo_mutex_recursion = 0;
+
+int
+pseudo_getlock() {
+ if (pthread_equal(pseudo_mutex_holder, pthread_self())) {
+ ++pseudo_mutex_recursion;
+ return 0;
+ } else {
+ if (pthread_mutex_lock(&pseudo_mutex) == 0) {
+ pseudo_mutex_recursion = 1;
+ pseudo_mutex_holder = pthread_self();
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+}
+
+void
+pseudo_droplock() {
+ if (--pseudo_mutex_recursion == 0) {
+ pseudo_mutex_holder = 0;
+ pthread_mutex_unlock(&pseudo_mutex);
+ }
+}
+
+void
+pseudo_antimagic() {
+ ++antimagic;
+}
+
+void
+pseudo_magic() {
+ if (antimagic > 0)
+ --antimagic;
+}
+
+EOF
+
+cat >&6 <<EOF
+`cat guts/COPYRIGHT`
+EOF
+
+# the wrapper function table is also #included, it is a separate file so it
+# can be written as we go, but still be a single table.
+cat >&7 <<EOF
+`cat guts/COPYRIGHT`
+/* The table of wrapper functions to populate */
+
+/* This file is generated and should not be modified. See the makewrappers
+ * script if you want to modify this. */
+static struct {
+ char *name; /* the name */
+ int (**real)(void); /* the underlying syscall */
+ int (*dummy)(void); /* the always-fails form */
+ int (*wrapper)(void); /* the wrapper from guts/name.c */
+} pseudo_functions[] = {
+EOF
+
+printf >&2 'Reading signatures...\n'
+for file in "$@"
+do
+ # read lines containing wrappable functions, write wrapper
+ # declarations, definitions, and so on.
+ printf >&2 '[%s]' "$file"
+ while read signature
+ do
+ # skip comments
+ case $signature in
+ \#*) continue;;
+ esac
+ # obtain return type, name, and arguments
+ args=`expr "$signature" : '.*(\(.*\));'`
+ return_and_name=`expr "$signature" : '\(.*\)('`
+ name=`expr "$return_and_name" : '.*[^a-zA-Z0-9_]\([a-zA-Z0-9_]*\)$'`
+ type=`expr "$return_and_name" : '\(.*[^ ]\) *'"$name"'$'`
+ printf >&2 ' %s' "$name"
+ argnames=''
+ save_IFS=$IFS
+ IFS=,
+ set -- $args
+ IFS=$save_ifs
+ args=''
+ optional_arg=false
+ for arg
+ do
+ # strip whitespace
+ arg=${arg# }
+ arg=${arg% }
+
+ # handle optional arguments, like the third arg
+ # to open()
+ case $arg in
+ ...*)
+ optional_arg=true
+ args="$args${args:+, }..."
+ arg=`expr "$arg" : '\.\.\.{\(.*\)}'`
+ argname=`expr "$arg" : '.*[^a-zA-Z0-9_]\([a-zA-Z0-9_]*\)$'`
+ argnames="$argnames${argnames:+, }$argname"
+
+ # we need this to extract and pass the argument
+ optional_decl=$arg
+ optional_prev=$prev_argname
+ optional_name=$argname
+ optional_type=`expr "$arg" : '\(.*[^ ]\) *'"$argname"'$'`
+ ;;
+ *)
+ argname=`expr "$arg" : '.*[^a-zA-Z0-9_]\([a-zA-Z0-9_]*\)$'`
+ args="$args${args:+, }$arg"
+ argnames="$argnames${argnames:+, }$argname"
+ prev_argname=$argname
+ ;;
+ esac
+ done
+
+ # determine default return value.
+ case $type in
+ int)
+ default_value=-1;;
+ uid_t|gid_t)
+ default_value=0;;
+ 'FILE *')
+ default_value=NULL;;
+ *) echo >&2 "Unknown type '$type'." ; exit 1 ;;
+ esac
+ # create the wrappers
+ # first the dummy, and the function pointer:
+ cat >&5 <<EOF
+static $type
+dummy_$name($args) {
+ pseudo_enosys("$name");
+ errno = ENOSYS;
+ return $default_value;
+}
+
+static $type (*real_$name)($args) = dummy_$name;
+
+EOF
+ # then the wrapper signature and args:
+ if $optional_arg; then
+ cat >&5 <<EOF
+$type
+$name($args) {
+ $optional_decl;
+ va_list ap;
+ va_start(ap, $optional_prev);
+ $optional_name = va_arg(ap, $optional_type);
+ va_end(ap);
+
+EOF
+ else
+ cat >&5 <<EOF
+$type
+$name($args) {
+EOF
+ fi
+ # and now the body of the wrapper:
+ cat >&5 <<EOF
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ return $default_value;
+ }
+ if (pseudo_populate_wrappers()) {
+ $type rc = $default_value;
+ int save_errno;
+ if (antimagic > 0) {
+ if (real_$name) {
+ rc = (*real_$name)($argnames);
+ } else {
+ rc = dummy_$name($argnames);
+ }
+ } else {
+ rc = wrap_$name($argnames);
+ }
+ save_errno = errno;
+ pseudo_droplock();
+ errno = save_errno;
+ return rc;
+ } else {
+ pseudo_droplock();
+ return dummy_$name($argnames);
+ }
+}
+
+EOF
+ # and now the signature part for the actual implementation:
+ # and the guts include file.
+
+ # the wrapper function is actually declared in
+ # pseudo_wrapper.c, with guts implemented in a separate
+ # file with comments indicating the signature.
+ guts="guts/$name.c"
+
+ # the actual wrapper function, including argument setup
+ if $optional_arg; then
+ cat >&5 << EOF
+static $type
+wrap_$name($args) {
+ $type rc = $default_value;
+ $optional_decl;
+
+ va_list ap;
+ va_start(ap, $optional_prev);
+ $optional_name = va_arg(ap, $optional_type);
+ va_end(ap);
+
+#include "$guts"
+
+ return rc;
+}
+EOF
+ else
+ cat >&5 << EOF
+static $type
+wrap_$name($args) {
+ $type rc = $default_value;
+
+#include "$guts"
+
+ return rc;
+}
+EOF
+ fi
+
+ # if the guts file didn't already exist, create a default.
+ if test ! -f "$guts"; then
+ if $optional_arg; then
+ cat > "$guts" <<EOF
+/*
+ * static $type
+ * wrap_$name($args$optional_decl) {
+ * $type rc = $default_value;
+ */
+
+ rc = real_$name($argnames);
+
+/* return rc;
+ * }
+ */
+EOF
+ else
+ cat > "$guts" <<EOF
+/*
+ * static $type
+ * wrap_$name($args) {
+ * $type rc = $default_value;
+ */
+
+ rc = real_$name($argnames);
+
+/* return rc;
+ * }
+ */
+EOF
+ fi
+ fi
+ # prototypes for pseudo_wrappers.h
+ cat >&6 <<EOF
+/* $type $name($args); */
+static $type dummy_$name($args);
+static $type wrap_$name($args);
+static $type (*real_$name)($args);
+
+EOF
+
+ # and entries in the Big Table
+ cat >&7 <<EOF
+ { /* $type $name($args); */
+ "$name",
+ (int (**)(void)) &real_$name,
+ (int (*)(void)) dummy_$name,
+ (int (*)(void)) wrap_$name
+ },
+EOF
+ done < $file
+done
+printf >&2 '.\n'
+
+# sentinel values
+cat >&7 <<EOF
+ { NULL, NULL, NULL, NULL },
+};
+EOF
+
+# and now the actual populate_wrappers function.
+cat >&5 <<EOF
+#include "pseudo_wrapper_table.c"
+
+extern char *program_invocation_short_name;
+
+static void
+pseudo_enosys(const char *func) {
+ pseudo_diag("pseudo: ENOSYS for '%s'.\n", func ? func : "<nil>");
+ if (getenv("PSEUDO_ENOSYS_ABORT"))
+ abort();
+}
+
+static int
+pseudo_populate_wrappers(void) {
+ int i;
+ char *debug;
+ static int done = 0;
+ char *pseudo_path = 0;
+
+ if (done)
+ return done;
+ pseudo_getlock();
+ pseudo_antimagic();
+ for (i = 0; pseudo_functions[i].name; ++i) {
+ if (*pseudo_functions[i].real == pseudo_functions[i].dummy) {
+ int (*f)(void);
+ char *e;
+ dlerror();
+ f = dlsym(RTLD_NEXT, pseudo_functions[i].name);
+ if ((e = dlerror()) != NULL) {
+ /* leave it pointed to dummy */
+ pseudo_diag("No wrapper for %s: %s\n", pseudo_functions[i].name, e);
+ } else {
+ if (f)
+ *pseudo_functions[i].real = f;
+ }
+ }
+ }
+ done = 1;
+ debug = getenv("PSEUDO_DEBUG");
+ if (debug) {
+ int level = atoi(debug);
+ for (i = 0; i < level; ++i) {
+ pseudo_debug_verbose();
+ }
+ }
+ /* must happen after wrappers are set up, because it can call
+ * getcwd(), which needs wrappers, but must happen here so that
+ * any attempt to use a path in a wrapper function will have a
+ * value for cwd.
+ */
+ pseudo_client_reset();
+ pseudo_path = pseudo_prefix_path(NULL);
+ if (pseudo_dir_fd == -1) {
+ if (pseudo_path) {
+ pseudo_dir_fd = open(pseudo_path, O_RDONLY);
+ pseudo_dir_fd = pseudo_fd(pseudo_dir_fd, MOVE_FD);
+ free(pseudo_path);
+ } else {
+ pseudo_diag("No prefix available to to find server.\n");
+ exit(1);
+ }
+ if (pseudo_dir_fd == -1) {
+ pseudo_diag("Can't open prefix path (%s) for server.\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+ pseudo_debug(2, "(%s) set up wrappers\n", program_invocation_short_name);
+ pseudo_magic();
+ pseudo_droplock();
+ return done;
+}
+EOF