From 5a894597830afe559264839b23a5ada4282417fd Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 20 Jul 2018 07:56:09 -0600 Subject: [PATCH] libs/libc/unistd/: Add a crippled version of daemon(). --- include/unistd.h | 1 + libs/libc/unistd/Make.defs | 2 +- libs/libc/unistd/lib_daemon.c | 172 ++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 libs/libc/unistd/lib_daemon.c diff --git a/include/unistd.h b/include/unistd.h index 2ac53b5204..f9e92f8633 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -290,6 +290,7 @@ void _exit(int status) noreturn_function; unsigned int sleep(unsigned int seconds); int usleep(useconds_t usec); int pause(void); +int daemon(int nochdir, int noclose); /* File descriptor operations */ diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs index c9582c5217..f258bd9fcd 100644 --- a/libs/libc/unistd/Make.defs +++ b/libs/libc/unistd/Make.defs @@ -35,7 +35,7 @@ # Add the unistd C files to the build -CSRCS += lib_access.c lib_swab.c lib_sysconf.c +CSRCS += lib_access.c lib_daemon.c lib_swab.c lib_sysconf.c CSRCS += lib_getopt.c lib_getoptargp.c lib_getoptindp.c lib_getoptoptp.c ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) diff --git a/libs/libc/unistd/lib_daemon.c b/libs/libc/unistd/lib_daemon.c new file mode 100644 index 0000000000..07fd0bac03 --- /dev/null +++ b/libs/libc/unistd/lib_daemon.c @@ -0,0 +1,172 @@ +/**************************************************************************** + * libs/libc/unistd/lib_daemon.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/* Not appropriate for use within the OS */ + +#if defined(CONFIG_BUILD_FLAT) || !defined(__KERNEL__) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: daemon + * + * Description: + * The daemon() function is for programs wishing to detach themselves from + * the controlling terminal and run in the background as system daemons. + * + * NOTE: daemon() is a non-standard GNU C library interface (based on a + * BSD interface of the same way which behaves slightly differently). + * The interfaces defined at OpenGroup.org are the interfaces that govern + * NuttX. deamon() is only described in the Linux man pages like:\ + * http://man7.org/linux/man-pages/man3/daemon.3.html + * + * Limitations: + * NuttX does not implement controlling terminals so the primary purpose + * of this interface is not supported. Additional operations controlled + * by input parameters are supported, however. + * + * It is not possible to support a true Linux daemon() helper function + * because it is designed to work only in the Linux environment and cannot + * be translated to NuttX. The above mentioned web page states: + * + * (This function forks, and if the fork(2) succeeds, the parent calls + * _exit(2), so that further errors are seen by the child only.) On + * + * So the basic operation of the NuttX daemon() is different. The GNU C + * library daemon() begins will logic like: + * + * switch (fork()) + * { + * case -1: + * return -1; + * case 0: + * break; + * default: + * exit(0); + * } + * + * This implementation begins essentially 'pretending' that we forked + * and that the fork was successful and that we are the child of the + * vim fork. + * + * Input Parameters: + * nochdir - If nochdir is zero, daemon() changes the process's current + * working directory to the root directory ("/"); otherwise, the current + * working directory is left unchanged. + * noclose - If noclose is zero, daemon() redirects standard input, + * standard output and standard error to /dev/null; otherwise, no changes + * are made to these file descriptors. + * + * Returned Value: + * 0 is returned on success; otherwise, -1 is returned with errno set + * appropriately. + * + ****************************************************************************/ + +int daemon(int nochdir, int noclose) +{ +#ifndef CONFIG_DISABLE_ENVIRON + if (nochdir == 0) + { + int ret = chdir("/"); + if (ret < 0) + { + return -1; /* chdir() will set the errno variable */ + } + } +#endif + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if (noclose == 0) + { + int fd = open("/dev/null", O_RDWR); + if (fd < 0) + { + return -1; + } + + /* Make sure the stdin, stdout, and stderr are closed */ + + (void)fclose(stdin); + (void)fclose(stdout); + (void)fclose(stderr); + + /* Dup the fd to create standard fd 0-2 */ + + (void)dup2(fd, 0); + (void)dup2(fd, 1); + (void)dup2(fd, 2); + + /* fdopen to get the stdin, stdout and stderr streams. The + * following logic depends on the fact that the library layer + * will allocate FILEs in order. And since we closed stdin, + * stdout, and stderr above, that is what we should get. + * + * fd = 0 is stdin (read-only) + * fd = 1 is stdout (write-only, append) + * fd = 2 is stderr (write-only, append) + */ + + (void)fdopen(0, "r"); + (void)fdopen(1, "a"); + (void)fdopen(2, "a"); + + /* We can close the original file descriptor now (unless it was + * one of* 0-2) + */ + + if (fd > 2) + { + (void)close(fd); + } + } +#endif + + return OK; +} + +#endif /* CONFIG_BUILD_FLAT=y || !__KERNEL__ */