#DPATCHLEVEL=0
---
# linux-user/syscall.c |   33 ++++++++++++++++++++++++++++++---
# 1 file changed, 30 insertions(+), 3 deletions(-)
#
Index: linux-user/syscall.c
===================================================================
--- linux-user/syscall.c.orig	2007-06-13 11:51:54.000000000 +0100
+++ linux-user/syscall.c	2007-06-13 11:52:17.000000000 +0100
@@ -52,6 +52,7 @@
 //#include <sys/user.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
+#include <sys/sysctl.h>
 
 #define termios host_termios
 #define winsize host_winsize
@@ -3912,9 +3913,35 @@ long do_syscall(void *cpu_env, int num, 
         break;
 #endif
     case TARGET_NR__sysctl:
-        /* We don't implement this, but ENODIR is always a safe
-           return value. */
-        return -ENOTDIR;
+        {
+            struct __sysctl_args *args = (struct __sysctl_args *) arg1;
+            int *name_target, *name, nlen, *oldlenp, oldlen, newlen, i;
+            void *oldval, *newval;
+
+            name_target = (int *) tswapl((long) args->name);
+            nlen = tswapl(args->nlen);
+            oldval = (void *) tswapl((long) args->oldval);
+            oldlenp = (int *) tswapl((long) args->oldlenp);
+            oldlen = tswapl(*oldlenp);
+            newval = (void *) tswapl((long) args->newval);
+            newlen = tswapl(args->newlen);
+
+            name = alloca(nlen * sizeof (int));
+            for (i = 0; i < nlen; i++)
+                name[i] = tswapl(name_target[i]);
+
+            if (nlen == 2 && name[0] == CTL_KERN && name[1] == KERN_VERSION) {
+                ret = get_errno(
+                        sysctl(name, nlen, oldval, &oldlen, newval, newlen));
+                if (!is_error(ret)) {
+                    *oldlenp = tswapl(oldlen);
+                }
+            } else {
+                gemu_log("qemu: Unsupported sysctl name\n");
+                ret = -ENOSYS;
+            }
+        }
+        break;
     case TARGET_NR_sched_setparam:
         {
             struct sched_param *target_schp;
