Move sysctl parser to a separate file

* sysctl.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* system.c: Move sys_sysctl and related code to sysctl.c.
diff --git a/sysctl.c b/sysctl.c
new file mode 100644
index 0000000..70cc5d9
--- /dev/null
+++ b/sysctl.c
@@ -0,0 +1,170 @@
+#include "defs.h"
+
+#include <linux/sysctl.h>
+
+#include "xlat/sysctl_root.h"
+#include "xlat/sysctl_kern.h"
+#include "xlat/sysctl_vm.h"
+#include "xlat/sysctl_net.h"
+#include "xlat/sysctl_net_core.h"
+#include "xlat/sysctl_net_unix.h"
+#include "xlat/sysctl_net_ipv4.h"
+#include "xlat/sysctl_net_ipv4_route.h"
+#include "xlat/sysctl_net_ipv4_conf.h"
+#include "xlat/sysctl_net_ipv6.h"
+#include "xlat/sysctl_net_ipv6_route.h"
+
+int
+sys_sysctl(struct tcb *tcp)
+{
+	struct __sysctl_args info;
+	int *name;
+	unsigned long size;
+
+	if (umove(tcp, tcp->u_arg[0], &info) < 0)
+		return printargs(tcp);
+
+	size = sizeof(int) * (unsigned long) info.nlen;
+	name = (size / sizeof(int) != (unsigned long) info.nlen) ? NULL : malloc(size);
+	if (name == NULL ||
+	    umoven(tcp, (unsigned long) info.name, size, (char *) name) < 0) {
+		free(name);
+		if (entering(tcp))
+			tprintf("{%p, %d, %p, %p, %p, %lu}",
+				info.name, info.nlen, info.oldval,
+				info.oldlenp, info.newval, (unsigned long)info.newlen);
+		return 0;
+	}
+
+	if (entering(tcp)) {
+		unsigned int cnt = 0, max_cnt;
+
+		tprints("{{");
+
+		if (info.nlen == 0)
+			goto out;
+		printxval(sysctl_root, name[0], "CTL_???");
+		++cnt;
+
+		if (info.nlen == 1)
+			goto out;
+		switch (name[0]) {
+		case CTL_KERN:
+			tprints(", ");
+			printxval(sysctl_kern, name[1], "KERN_???");
+			++cnt;
+			break;
+		case CTL_VM:
+			tprints(", ");
+			printxval(sysctl_vm, name[1], "VM_???");
+			++cnt;
+			break;
+		case CTL_NET:
+			tprints(", ");
+			printxval(sysctl_net, name[1], "NET_???");
+			++cnt;
+
+			if (info.nlen == 2)
+				goto out;
+			switch (name[1]) {
+			case NET_CORE:
+				tprints(", ");
+				printxval(sysctl_net_core, name[2],
+					  "NET_CORE_???");
+				break;
+			case NET_UNIX:
+				tprints(", ");
+				printxval(sysctl_net_unix, name[2],
+					  "NET_UNIX_???");
+				break;
+			case NET_IPV4:
+				tprints(", ");
+				printxval(sysctl_net_ipv4, name[2],
+					  "NET_IPV4_???");
+
+				if (info.nlen == 3)
+					goto out;
+				switch (name[2]) {
+				case NET_IPV4_ROUTE:
+					tprints(", ");
+					printxval(sysctl_net_ipv4_route,
+						  name[3],
+						  "NET_IPV4_ROUTE_???");
+					break;
+				case NET_IPV4_CONF:
+					tprints(", ");
+					printxval(sysctl_net_ipv4_conf,
+						  name[3],
+						  "NET_IPV4_CONF_???");
+					break;
+				default:
+					goto out;
+				}
+				break;
+			case NET_IPV6:
+				tprints(", ");
+				printxval(sysctl_net_ipv6, name[2],
+					  "NET_IPV6_???");
+
+				if (info.nlen == 3)
+					goto out;
+				switch (name[2]) {
+				case NET_IPV6_ROUTE:
+					tprints(", ");
+					printxval(sysctl_net_ipv6_route,
+						  name[3],
+						  "NET_IPV6_ROUTE_???");
+					break;
+				default:
+					goto out;
+				}
+				break;
+			default:
+				goto out;
+			}
+			break;
+		default:
+			goto out;
+		}
+	out:
+		max_cnt = info.nlen;
+		if (abbrev(tcp) && max_cnt > max_strlen)
+			max_cnt = max_strlen;
+		while (cnt < max_cnt)
+			tprintf(", %x", name[cnt++]);
+		if (cnt < (unsigned) info.nlen)
+			tprints(", ...");
+		tprintf("}, %d, ", info.nlen);
+	} else {
+		size_t oldlen = 0;
+		if (info.oldval == NULL) {
+			tprints("NULL");
+		} else if (umove(tcp, (long)info.oldlenp, &oldlen) >= 0
+			   && info.nlen >= 2
+			   && ((name[0] == CTL_KERN
+				&& (name[1] == KERN_OSRELEASE
+				    || name[1] == KERN_OSTYPE
+#ifdef KERN_JAVA_INTERPRETER
+				    || name[1] == KERN_JAVA_INTERPRETER
+#endif
+#ifdef KERN_JAVA_APPLETVIEWER
+				    || name[1] == KERN_JAVA_APPLETVIEWER
+#endif
+					)))) {
+			printpath(tcp, (size_t)info.oldval);
+		} else {
+			tprintf("%p", info.oldval);
+		}
+		tprintf(", %lu, ", (unsigned long)oldlen);
+		if (info.newval == NULL)
+			tprints("NULL");
+		else if (syserror(tcp))
+			tprintf("%p", info.newval);
+		else
+			printpath(tcp, (size_t)info.newval);
+		tprintf(", %lu", (unsigned long)info.newlen);
+	}
+
+	free(name);
+	return 0;
+}