about summary refs log tree commit diff
path: root/src/process
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2014-05-29 21:01:32 -0400
committerRich Felker <dalias@aerifal.cx>2014-05-29 21:01:32 -0400
commitdd5f50da6f6c3df5647e922e47f8568a8896a752 (patch)
treec5ab9a1006d2ab4c449f8fa922ce3237acad30e4 /src/process
parent2e55da911896a91e95b24ab5dc8a9d9b0718f4de (diff)
downloadmusl-dd5f50da6f6c3df5647e922e47f8568a8896a752.tar.gz
musl-dd5f50da6f6c3df5647e922e47f8568a8896a752.tar.xz
musl-dd5f50da6f6c3df5647e922e47f8568a8896a752.zip
support linux kernel apis (new archs) with old syscalls removed
such archs are expected to omit definitions of the SYS_* macros for
syscalls their kernels lack from arch/$ARCH/bits/syscall.h. the
preprocessor is then able to select the an appropriate implementation
for affected functions. two basic strategies are used on a
case-by-case basis:

where the old syscalls correspond to deprecated library-level
functions, the deprecated functions have been converted to wrappers
for the modern function, and the modern function has fallback code
(omitted at the preprocessor level on new archs) to make use of the
old syscalls if the new syscall fails with ENOSYS. this also improves
functionality on older kernels and eliminates the incentive to program
with deprecated library-level functions for the sake of compatibility
with older kernels.

in other situations where the old syscalls correspond to library-level
functions which are not deprecated but merely lack some new features,
such as the *at functions, the old syscalls are still used on archs
which support them. this may change at some point in the future if or
when fallback code is added to the new functions to make them usable
(possibly with reduced functionality) on old kernels.
Diffstat (limited to 'src/process')
-rw-r--r--src/process/fork.c5
-rw-r--r--src/process/posix_spawn.c18
2 files changed, 21 insertions, 2 deletions
diff --git a/src/process/fork.c b/src/process/fork.c
index 864c7d7a..f8cf21e7 100644
--- a/src/process/fork.c
+++ b/src/process/fork.c
@@ -1,5 +1,6 @@
 #include <unistd.h>
 #include <string.h>
+#include <signal.h>
 #include "syscall.h"
 #include "libc.h"
 #include "pthread_impl.h"
@@ -16,7 +17,11 @@ pid_t fork(void)
 	sigset_t set;
 	__fork_handler(-1);
 	__block_all_sigs(&set);
+#ifdef SYS_fork
 	ret = syscall(SYS_fork);
+#else
+	ret = syscall(SYS_clone, SIGCHLD, 0);
+#endif
 	if (libc.has_thread_pointer && !ret) {
 		pthread_t self = __pthread_self();
 		self->tid = self->pid = __syscall(SYS_getpid);
diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c
index 08644f51..08928b0e 100644
--- a/src/process/posix_spawn.c
+++ b/src/process/posix_spawn.c
@@ -22,6 +22,20 @@ struct args {
 
 void __get_handler_set(sigset_t *);
 
+static int __sys_dup2(int old, int new)
+{
+#ifdef SYS_dup2
+	return __syscall(SYS_dup2, old, new);
+#else
+	if (old==new) {
+		int r = __syscall(SYS_fcntl, old, F_GETFD);
+		return r<0 ? r : old;
+	} else {
+		return __syscall(SYS_dup3, old, new, 0);
+	}
+#endif
+}
+
 static int child(void *args_vp)
 {
 	int i, ret;
@@ -92,14 +106,14 @@ static int child(void *args_vp)
 					goto fail;
 				break;
 			case FDOP_DUP2:
-				if ((ret=__syscall(SYS_dup2, op->srcfd, op->fd))<0)
+				if ((ret=__sys_dup2(op->srcfd, op->fd))<0)
 					goto fail;
 				break;
 			case FDOP_OPEN:
 				fd = __sys_open(op->path, op->oflag, op->mode);
 				if ((ret=fd) < 0) goto fail;
 				if (fd != op->fd) {
-					if ((ret=__syscall(SYS_dup2, fd, op->fd))<0)
+					if ((ret=__sys_dup2(fd, op->fd))<0)
 						goto fail;
 					__syscall(SYS_close, fd);
 				}