diff --git a/kernel/syscall.c b/kernel/syscall.c index 564a9dbf..f5329367 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -85,23 +85,6 @@ static int sys_open(const char* name, int flags, int mode) return fd; } -static int sys_dup(int fd) -{ - task_t* curr_task = per_core(current_task); - int new_fd; - - if (BUILTIN_EXPECT(fd >= NR_OPEN, 0)) - return -EINVAL; - if (curr_task->fildes_table[fd]->node == NULL) - return -EINVAL; - - new_fd = get_fildes(); - curr_task->fildes_table[new_fd] = curr_task->fildes_table[fd]; - curr_task->fildes_table[fd]->count++; - - return new_fd; -} - static int sys_stat(const char* name, struct stat* st) { vfs_node_t* node; @@ -229,6 +212,45 @@ static int sys_lseek(int fd, off_t pos, int origin) return ret; } +static int sys_dup(int fd) +{ + task_t* curr_task = per_core(current_task); + int new_fd; + + if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0)) + return -EBADF; + if (curr_task->fildes_table[fd] == NULL) + return -EBADF; + + new_fd = get_fildes(); + curr_task->fildes_table[new_fd] = curr_task->fildes_table[fd]; + curr_task->fildes_table[fd]->count++; + + return new_fd; +} + +static int sys_dup2(int fd, int fd2) +{ + task_t* curr_task = per_core(current_task); + + if (BUILTIN_EXPECT((fd >= NR_OPEN) || (fd < 0), 0)) + return -EBADF; + if (BUILTIN_EXPECT((fd2 >= NR_OPEN) || (fd2 < 0), 0)) + return -EBADF; + if (curr_task->fildes_table[fd] == NULL) + return -EBADF; + + if (fd == fd2) + return fd2; + if (curr_task->fildes_table[fd2] != NULL) + sys_close(fd2); + + curr_task->fildes_table[fd2] = curr_task->fildes_table[fd]; + curr_task->fildes_table[fd]->count++; + + return fd2; +} + static int sys_sbrk(int incr) { task_t* task = per_core(current_task); @@ -294,8 +316,13 @@ int syscall_handler(uint32_t sys_nr, ...) } case __NR_dup: { int fd = va_arg(vl, int); - if (fd >= 0) - ret = sys_dup(fd); + ret = sys_dup(fd); + break; + } + case __NR_dup2: { + int fd = va_arg(vl, int); + int fd2 = va_arg(vl, int); + ret = sys_dup2(fd, fd2); break; } case __NR_stat: { diff --git a/newlib/examples/rlogind.c b/newlib/examples/rlogind.c index 2acd970c..80380ffc 100644 --- a/newlib/examples/rlogind.c +++ b/newlib/examples/rlogind.c @@ -86,12 +86,9 @@ int main(int argc, char* argv[]) char* newenv[] = {"USER=root", "PATH=/bin:/sbin:/usr/bin", "PWD=/", "TEMP=/tmp", NULL}; // set stdout, stdin and stderr to the socket descriptor - close(STDIN_FILENO); - dup(sockd2); - close(STDOUT_FILENO); - dup(sockd2); - close(STDERR_FILENO); - dup(sockd2); + dup2(sockd2, STDIN_FILENO); + dup2(sockd2, STDOUT_FILENO); + dup2(sockd2, STDERR_FILENO); close(sockd2); execve("/bin/mshell", newargs, newenv); diff --git a/newlib/src/libgloss/metalsvm/Makefile.in b/newlib/src/libgloss/metalsvm/Makefile.in index fc42bfe8..2c37179d 100644 --- a/newlib/src/libgloss/metalsvm/Makefile.in +++ b/newlib/src/libgloss/metalsvm/Makefile.in @@ -63,7 +63,8 @@ CRT0 = crt0.o METALSVM_BSP = libgloss.a METALSVM_OBJS = chown.o errno.o fork.o gettod.o kill.o open.o sbrk.o times.o write.o \ close.o execve.o fstat.o init.o link.o read.o stat.o unlink.o \ - environ.o _exit.o getpid.o isatty.o lseek.o readlink.o symlink.o wait.o dup.o + environ.o _exit.o getpid.o isatty.o lseek.o readlink.o symlink.o wait.o \ + dup.o dup2.o #### Host specific Makefile fragment comes in here. @@ -104,6 +105,7 @@ readlink.o: $(srcdir)/readlink.c symlink.o: $(srcdir)/symlink.c wait.o: $(srcdir)/wait.c dup.o: $(srcdir)/dup.c +dup.o: $(srcdir)/dup2.c install: $($(CPU)_INSTALL) $(INSTALL_DATA) $(CRT0) $(DESTDIR)$(tooldir)/lib${MULTISUBDIR}/$(CRT0) diff --git a/newlib/src/libgloss/metalsvm/dup2.c b/newlib/src/libgloss/metalsvm/dup2.c new file mode 100644 index 00000000..00cbe32b --- /dev/null +++ b/newlib/src/libgloss/metalsvm/dup2.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011, Marian Ohligs, Chair for Operating Systems, + * RWTH Aachen University + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen University + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of MetalSVM. + */ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + +int +_DEFUN (dup2, (fildes, fildes2), + int fildes _AND + int fildes2) +{ + int ret; + + ret = SYSCALL2(__NR_dup2, fildes, fildes2); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +}