diff --git a/libc/Makefile b/libc/Makefile
index d48c6904..55af2be9 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -124,6 +124,7 @@ $(CPUDIR)/signal.o \
$(CPUDIR)/syscall.o \
dispmsg_issue.o \
dlfcn.o \
+dup2.o \
dup.o \
env.o \
errorprint.o \
diff --git a/libc/dup2.cpp b/libc/dup2.cpp
new file mode 100644
index 00000000..6c9264ec
--- /dev/null
+++ b/libc/dup2.cpp
@@ -0,0 +1,33 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of the Sortix C Library.
+
+ The Sortix C Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or (at your
+ option) any later version.
+
+ The Sortix C Library 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 GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with the Sortix C Library. If not, see .
+
+ dup2.cpp
+ Duplicates a file descriptor.
+
+*******************************************************************************/
+
+#include
+#include
+
+DEFN_SYSCALL2(int, sys_dup2, SYSCALL_DUP2, int, int);
+
+extern "C" int dup2(int oldfd, int newfd)
+{
+ return sys_dup2(oldfd, newfd);
+}
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index b1936082..0640cda6 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -91,7 +91,6 @@ unsigned alarm(unsigned);
size_t confstr(int, char*, size_t);
char* crypt(const char*, const char*);
char* ctermid(char*);
-int dup2(int, int);
void encrypt(char [64], int);
int faccessat(int, const char*, int, int);
int fchdir(int);
@@ -153,6 +152,7 @@ int access(const char*, int);
int chdir(const char*);
int chown(const char*, uid_t, gid_t);
int close(int);
+int dup2(int, int);
int dup(int);
void _exit(int) __attribute__ ((noreturn));
int execl(const char*, const char*, ...);
diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h
index 6a19dd6a..08fc24e1 100644
--- a/sortix/include/sortix/syscallnum.h
+++ b/sortix/include/sortix/syscallnum.h
@@ -81,6 +81,7 @@
#define SYSCALL_CHMOD 57
#define SYSCALL_CHOWN 58
#define SYSCALL_LINK 59
-#define SYSCALL_MAX_NUM 60 /* index of highest constant + 1 */
+#define SYSCALL_DUP2 60
+#define SYSCALL_MAX_NUM 61 /* index of highest constant + 1 */
#endif
diff --git a/sortix/io.cpp b/sortix/io.cpp
index 081c2c7e..7a5ce2ab 100644
--- a/sortix/io.cpp
+++ b/sortix/io.cpp
@@ -122,6 +122,12 @@ static int sys_dup(int fd)
return dtable->Allocate(desc, 0);
}
+static int sys_dup2(int oldfd, int newfd)
+{
+ Ref dtable = CurrentProcess()->GetDTable();
+ return dtable->Copy(oldfd, newfd);
+}
+
// TODO: If this function fails the file may still have been created. Does a
// standard prohibit this and is that the wrong thing?
static int sys_openat(int dirfd, const char* path, int flags, mode_t mode)
@@ -424,6 +430,7 @@ void Init()
Syscall::Register(SYSCALL_CHOWN, (void*) sys_chown);
Syscall::Register(SYSCALL_CLOSE, (void*) sys_close);
Syscall::Register(SYSCALL_DUP, (void*) sys_dup);
+ Syscall::Register(SYSCALL_DUP2, (void*) sys_dup2);
Syscall::Register(SYSCALL_FCNTL, (void*) sys_fcntl);
Syscall::Register(SYSCALL_FSTATAT, (void*) sys_fstatat);
Syscall::Register(SYSCALL_FSTAT, (void*) sys_fstat);