Begin work on supporting clone
diff --git a/ChangeLog b/ChangeLog
index 959068c..e7b1c87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@
 
   * Merge patch from ftp://oss.software.ibm.com/linux390/ to add
     support for Linux on the IBM S/390 architecture
+  * process.c: add internal_clone(), currently only shows the options
+  * syscall.c: use internal_clone to handle SYS_clone
 
 Mon Dec 20 00:27:50 CET 1999 Wichert Akkerman <wakkerma@debian.org>
 
diff --git a/defs.h b/defs.h
index d65fc15..cae320a 100644
--- a/defs.h
+++ b/defs.h
@@ -336,6 +336,9 @@
 extern void fake_execve P((struct tcb *, char *, char *[], char *[]));
 extern void printtv32 P((struct tcb*, long));
 
+#ifdef LINUX
+extern int internal_clone P((struct tcb *));
+#endif
 extern int internal_fork P((struct tcb *));
 extern int internal_exec P((struct tcb *));
 extern int internal_wait P((struct tcb *));
diff --git a/process.c b/process.c
index ea78824..ae7b8e4 100644
--- a/process.c
+++ b/process.c
@@ -78,7 +78,7 @@
 #define WCOREDUMP(status) ((status) & 0200)
 #endif
 
-/* WTA: this has `&& !defined(LINUXSPARC)', this seems unneeded though? */
+/* WTA: this was `&& !defined(LINUXSPARC)', this seems unneeded though? */
 #if defined(HAVE_PRCTL)
 static struct xlat prctl_options[] = {
 #ifdef PR_MAXPROCS
@@ -316,6 +316,35 @@
 
 #else /* !SVR4 */
 
+#ifdef LINUX
+
+/* defines copied from linux/sched.h since we can't include that
+ * ourselves (it conflicts with *lots* of libc includes)
+ */
+#define CSIGNAL         0x000000ff      /* signal mask to be sent at exit */
+#define CLONE_VM        0x00000100      /* set if VM shared between processes */
+#define CLONE_FS        0x00000200      /* set if fs info shared between processes */
+#define CLONE_FILES     0x00000400      /* set if open files shared between processes */
+#define CLONE_SIGHAND   0x00000800      /* set if signal handlers shared */
+#define CLONE_PID       0x00001000      /* set if pid shared */
+#define CLONE_PTRACE    0x00002000      /* set if we want to let tracing continue on the child too */
+#define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */
+#define CLONE_PARENT    0x00008000      /* set if we want to have the same parent as the cloner */
+
+static struct xlat clone_flags[] = {
+    { CLONE_VM,		"CLONE_VM"	},
+    { CLONE_FS,		"CLONE_FS"	},
+    { CLONE_FILES,	"CLONE_FILES"	},
+    { CLONE_SIGHAND,	"CLONE_SIGHAND"	},
+    { CLONE_PID,	"CLONE_PID"	},
+    { CLONE_PTRACE,	"CLONE_PTRACE"	},
+    { CLONE_VFORK,	"CLONE_VFORK"	},
+    { CLONE_PARENT,	"CLONE_PARENT"	},
+    { 0,		NULL		},
+};
+
+#endif
+
 int
 sys_fork(tcp)
 struct tcb *tcp;
@@ -325,6 +354,66 @@
 	return 0;
 }
 
+#ifdef SYS_clone
+int
+internal_clone(tcp)
+struct tcb *tcp;
+{
+	if (entering(tcp)) {
+		tprintf("fn=%#lx, child_stack=%#lx, flags=",
+				tcp->u_arg[0], tcp->u_arg[1]);
+		if (printflags(clone_flags, tcp->u_arg[2]) == 0)
+			tprintf("0");
+		tprintf(", args=%#lx", tcp->u_arg[3]);
+
+		/* For now we don't follow clone yet.. we're just preparing the code */
+		dont_follow = 1;
+
+		if (!followfork || dont_follow)
+			return 0;
+		if (nprocs == MAX_PROCS) {
+			tcp->flags &= ~TCB_FOLLOWFORK;
+			fprintf(stderr, "sys_fork: tcb table full\n");
+			return 0;
+		}
+		tcp->flags |= TCB_FOLLOWFORK;
+
+		/* XXX 
+		/* We will take the simple approach and add CLONE_PTRACE to the clone
+		 * options. This only works on Linux 2.2.x and later. This means that
+		 * we break all programs using clone on older kernels..
+		 * We should try to fallback to the bpt-trick if this fails, but right
+		 * now we don't.
+		 */
+
+		/* TODO: actually change the flags */
+	} else {
+		if (!(tcp->flags & TCB_FOLLOWFORK))
+			return 0;
+
+		if (syserror(tcp))
+			return 0;
+
+		pid = tcp->u_rval;
+		if ((tcpchild = alloctcb(pid)) == NULL) {
+			fprintf(stderr, " [tcb table full]\n");
+			kill(pid, SIGKILL); /* XXX */
+			return 0;
+		}
+
+		/* For fork we need to re-attach, but thanks to CLONE_PTRACE we're
+		 * already attached.
+		 */
+		tcphild->flags |= TCB_ATTACHED;
+		newoutf(tcpfhild);
+		tcp->nchildren++;
+		if (!qflag)
+			fprintf(stderr, "Process %d attached\n", pid);
+	}
+	return 0;
+}
+#endif
+
 int
 internal_fork(tcp)
 struct tcb *tcp;
@@ -349,9 +438,17 @@
 #endif
 #ifdef SYS_clone
 	/* clone can do many things, not all of which we know how to handle.
-	   Don't do it for now. */
-	if (tcp->scno == SYS_clone)
+	   Don't do much for now. */
+	if (tcp->scno == SYS_clone) {
+	    	if (entering(tcp)) {
+			tprintf("fn=%#lx, child_stack=%#lx, flags=",
+					tcp->u_arg[0], tcp->u_arg[1]);
+			if (printflags(clone_flags, tcp->u_arg[2]) == 0)
+			    tprintf("0");
+			tprintf(", args=%#lx", tcp->u_arg[3]);
+		}
 		dont_follow = 1;
+	}
 #endif
 	if (entering(tcp)) {
 		if (!followfork || dont_follow)
@@ -364,7 +461,7 @@
 		tcp->flags |= TCB_FOLLOWFORK;
 		if (setbpt(tcp) < 0)
 			return 0;
-	}
+  	}
 	else {
 		int bpt = tcp->flags & TCB_BPTSET;
 
diff --git a/syscall.c b/syscall.c
index 2b23471..19739a8 100644
--- a/syscall.c
+++ b/syscall.c
@@ -531,12 +531,13 @@
 #ifdef SYS_vfork
 	case SYS_vfork:
 #endif
-#ifdef SYS_clone
-	case SYS_clone:
-#endif
 		internal_fork(tcp);
 		break;
-
+#ifdef SYS_clone
+	case SYS_clone:
+		internal_clone(tcp);
+		break;
+#endif
 #ifdef SYS_execv
 	case SYS_execv:
 #endif
diff --git a/util.c b/util.c
index 5c38e66..2d55f8e 100644
--- a/util.c
+++ b/util.c
@@ -871,7 +871,6 @@
 
 #ifdef LINUX
 	long pc;
-
 #if defined(I386)
 	if (upeek(tcp->pid, 4*EIP, &pc) < 0)
 		return -1;
@@ -897,9 +896,7 @@
 	pc = regs.r_pc;
 #elif defined(S390)
 	if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
-		return -1;
-
-#else
+#endif
 	return pc;
 #endif /* LINUX */