diff --git a/qse/include/qse/si/AppRoot.hpp b/qse/include/qse/si/AppRoot.hpp new file mode 100644 index 00000000..4551f095 --- /dev/null +++ b/qse/include/qse/si/AppRoot.hpp @@ -0,0 +1,56 @@ +/* + * $Id$ + * + Copyright (c) 2006-2014 Chung, Hyung-Hwan. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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. + */ + +#ifndef _QSE_SI_APPROOT_H_ +#define _QSE_SI_APPROOT_H_ + +#include +#include + +///////////////////////////////// +QSE_BEGIN_NAMESPACE(QSE) +///////////////////////////////// + +class AppRoot: QSE::Uncopyable +{ +public: + AppRoot (): _root_only (false) {} + virtual ~AppRoot () {} + + int daemonize (bool chdir_to_root = true, int fork_count = 1) QSE_CPP_NOEXCEPT; + +protected: + bool _root_only; + + + void on_signal () QSE_CPP_NOEXCEPT; +}; + +///////////////////////////////// +QSE_END_NAMESPACE(QSE) +///////////////////////////////// + +#endif diff --git a/qse/include/qse/si/Makefile.am b/qse/include/qse/si/Makefile.am index 88880987..bdb091d5 100644 --- a/qse/include/qse/si/Makefile.am +++ b/qse/include/qse/si/Makefile.am @@ -19,6 +19,7 @@ pkginclude_HEADERS = \ pio.h \ rwl.h \ sck.h \ + sinfo.h \ sio.h \ task.h \ thr.h \ @@ -26,6 +27,7 @@ pkginclude_HEADERS = \ if ENABLE_CXX pkginclude_HEADERS += \ + AppRoot.hpp \ SocketAddress.hpp \ Socket.hpp endif diff --git a/qse/include/qse/si/Makefile.in b/qse/include/qse/si/Makefile.in index f724456d..5a7ac3fa 100644 --- a/qse/include/qse/si/Makefile.in +++ b/qse/include/qse/si/Makefile.in @@ -88,6 +88,7 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_CXX_TRUE@am__append_1 = \ +@ENABLE_CXX_TRUE@ AppRoot.hpp \ @ENABLE_CXX_TRUE@ SocketAddress.hpp \ @ENABLE_CXX_TRUE@ Socket.hpp @@ -130,8 +131,8 @@ am__can_run_installinfo = \ esac am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \ fio.h fs.h glob.h intr.h log.h mtx.h mux.h nwad.h nwif.h \ - nwio.h pio.h rwl.h sck.h sio.h task.h thr.h tio.h \ - SocketAddress.hpp Socket.hpp + nwio.h pio.h rwl.h sck.h sinfo.h sio.h task.h thr.h tio.h \ + AppRoot.hpp SocketAddress.hpp Socket.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -366,7 +367,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkginclude_HEADERS = aio.h aio-pro.h aio-sck.h cnd.h dir.h fio.h fs.h \ glob.h intr.h log.h mtx.h mux.h nwad.h nwif.h nwio.h pio.h \ - rwl.h sck.h sio.h task.h thr.h tio.h $(am__append_1) + rwl.h sck.h sinfo.h sio.h task.h thr.h tio.h $(am__append_1) all: all-am .SUFFIXES: diff --git a/qse/include/qse/si/sinfo.h b/qse/include/qse/si/sinfo.h new file mode 100644 index 00000000..4fbba8f0 --- /dev/null +++ b/qse/include/qse/si/sinfo.h @@ -0,0 +1,49 @@ +/* + * $Id$ + * + Copyright (c) 2006-2014 Chung, Hyung-Hwan. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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. + */ + +#ifndef _QSE_SI_SINFO_H_ +#define _QSE_SI_SINFO_H_ + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +QSE_EXPORT int qse_get_highest_fd (void); + +QSE_EXPORT int qse_close_open_fds_using_proc ( + int* excepts, + qse_size_t count +); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/qse/lib/cmn/syscall.h b/qse/lib/cmn/syscall.h index 09107556..c45e3c9d 100644 --- a/qse/lib/cmn/syscall.h +++ b/qse/lib/cmn/syscall.h @@ -69,6 +69,9 @@ #if defined(HAVE_DIRENT_H) # include #endif +#if defined(HAVE_SYS_IOCTL_H) +# include +#endif #if defined(QSE_USE_SYSCALL) && defined(HAVE_SYS_SYSCALL_H) # include @@ -214,6 +217,24 @@ # define QSE_GETEGID() getegid() #endif +#if defined(SYS_getsid) && defined(QSE_USE_SYSCALL) +# define QSE_GETSID(pid) syscall(SYS_getsid,pid) +#else +# define QSE_GETSID(pid) getsid(pid) +#endif + +#if defined(SYS_setsid) && defined(QSE_USE_SYSCALL) +# define QSE_SETSID() syscall(SYS_setsid) +#else +# define QSE_SETSID() setsid() +#endif + +#if defined(SYS_signal) && defined(QSE_USE_SYSCALL) +# define QSE_SIGNAL(signum,handler) syscall(SYS_signal,signum,handler) +#else +# define QSE_SIGNAL(signum,handler) signal(signum,handler) +#endif + #if defined(SYS_gettimeofday) && defined(QSE_USE_SYSCALL) # define QSE_GETTIMEOFDAY(tv,tz) syscall(SYS_gettimeofday,tv,tz) #else @@ -250,6 +271,12 @@ # define QSE_SETRLIMIT(res,lim) setrlimit(res,lim) #endif +#if defined(SYS_ioctl) && defined(QSE_USE_SYSCALL) +# define QSE_IOCTL(fd,req,arg) syscall(SYS_ioctl,fd,req,arg) +#else +# define QSE_IOCTL(fd,req,arg) ioctl(fd,req,arg) +#endif + /* ===== FILE SYSTEM CALLS ===== */ @@ -378,6 +405,12 @@ # define QSE_RENAME(oldpath,newpath) rename(oldpath,newpath) #endif +#if defined(SYS_umask) && defined(QSE_USE_SYSCALL) +# define QSE_UMASK(mode) syscall(SYS_umask,mode) +#else +# define QSE_UMASK(mode) umask(mode) +#endif + #if defined(SYS_mkdir) && defined(QSE_USE_SYSCALL) # define QSE_MKDIR(path,mode) syscall(SYS_mkdir,path,mode) #else @@ -390,6 +423,12 @@ # define QSE_RMDIR(path) rmdir(path) #endif +#if defined(SYS_chdir) && defined(QSE_USE_SYSCALL) +# define QSE_CHDIR(path) syscall(SYS_chdir,path) +#else +# define QSE_CHDIR(path) chdir(path) +#endif + #if defined(SYS_symlink) && defined(QSE_USE_SYSCALL) # define QSE_SYMLINK(oldpath,newpath) syscall(SYS_symlink,oldpath,newpath) #else diff --git a/qse/lib/si/AppRoot.cpp b/qse/lib/si/AppRoot.cpp new file mode 100644 index 00000000..1daa1896 --- /dev/null +++ b/qse/lib/si/AppRoot.cpp @@ -0,0 +1,153 @@ +/* + * $Id$ + * + Copyright (c) 2006-2014 Chung, Hyung-Hwan. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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. + */ + +#include +#include +#include "../cmn/syscall.h" + +///////////////////////////////// +QSE_BEGIN_NAMESPACE(QSE) +///////////////////////////////// + +int AppRoot::daemonize (bool chdir_to_root, int fork_count) QSE_CPP_NOEXCEPT +{ + if (this->_root_only && QSE_GETEUID() != 0) return -1; + + if (fork_count >= 1) + { + if (fork_count >= 2) + { + struct sigaction sa; + int n = QSE_FORK(); + if (n == -1) return -1; + if (n != 0) QSE_EXIT(0); + + QSE_SETSID (); + } + + int n = QSE_FORK(); + if (n == -1) + { + //throw DaemonError ("can't xp_fork"); + //if (err_code) *err_code = ERR_FORK; + return -1; + } + + // the parent exits + if (n != 0) QSE_EXIT(0); // TODO: should i call exit() in stdlib.h? + } + + QSE_UMASK (0); + if (chdir_to_root) QSE_CHDIR("/"); // don't care about failure + + if (true) + { + int keep[] = { 0, 1, 2}; + + if (qse_close_open_fds_using_proc (keep, QSE_COUNTOF(keep)) <= -1) + { + for (int i = qse_get_highest_fd(); i >= 3; i--) QSE_CLOSE (i); + } + + int fd = QSE_OPEN ("/dev/null", O_RDWR, 0); + if (fd >= 0) + { + if (fd != 0) QSE_DUP2 (fd, 0); + if (fd != 1) QSE_DUP2 (fd, 1); + if (fd != 2) QSE_DUP2 (fd, 2); + if (fd > 2) QSE_CLOSE (fd); + } + } + + if (fork_count <= 1) + { + if (fork_count <= 0) + { + // detach from the controlling terminal manually + // when no fork() is requested though setsid() is supposed to + // do this as well. + int fd = QSE_OPEN ("/dev/tty", O_RDWR, 0); + if (fd >= 0) + { + QSE_IOCTL(fd, TIOCNOTTY, NULL); + QSE_CLOSE (fd); + } + + // since no fork() has been executed, the process that has + // executed this process will remain as the parent. there + // will happen no orphaning of this process and take-over + // by init happen + } + + QSE_SETSID (); // don't care about failure + } + + return 0; +} + +#if 0 +int AppRoot::switchUser () QSE_CPP_NOEXCEPT +{ + struct passwd* pw; + + pw = getpwnam (username); + if (!pw) + + + if (QSE_SETGID(pw->pw_gid) == -1) + { + } + + QSE_SETEGID(gid); + QSE_SETUID(uid); + QSE_SETEUID(uid); + +} +#endif + +void AppRoot::on_signal () QSE_CPP_NOEXCEPT +{ +} + + +#if 0 +int main () +{ + AppRoot app; + + app.daemonize(); + app.switchUser ("nobody", "nobody"); + app.switchUser (10, 20); + app.catchSignal (SIGINT, xxxxx); + app.catchSignal (SIGTERM, xxx); + + return 0; +} +#endif + +///////////////////////////////// +QSE_END_NAMESPACE(QSE) +///////////////////////////////// diff --git a/qse/lib/si/Makefile.am b/qse/lib/si/Makefile.am index 3288d83a..4c62a38a 100644 --- a/qse/lib/si/Makefile.am +++ b/qse/lib/si/Makefile.am @@ -38,6 +38,7 @@ libqsesi_la_SOURCES = \ pio.c \ rwl.c \ sck.c \ + sinfo.c \ sio.c \ task.c \ thr.c \ @@ -51,6 +52,7 @@ libqsesi_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) $(SSL_LIBS) if ENABLE_CXX lib_LTLIBRARIES += libqsesixx.la libqsesixx_la_SOURCES = \ + AppRoot.cpp \ SocketAddress.cpp \ Socket.cpp libqsesixx_la_LDFLAGS = -L. -L../cmn -version-info 1:0:0 -no-undefined diff --git a/qse/lib/si/Makefile.in b/qse/lib/si/Makefile.in index 4d7684f2..d3797848 100644 --- a/qse/lib/si/Makefile.in +++ b/qse/lib/si/Makefile.in @@ -150,8 +150,8 @@ am_libqsesi_la_OBJECTS = libqsesi_la-aio.lo libqsesi_la-aio-pro.lo \ libqsesi_la-nwad.lo libqsesi_la-nwad-skad.lo \ libqsesi_la-nwif.lo libqsesi_la-nwif-cfg.lo \ libqsesi_la-nwio.lo libqsesi_la-pio.lo libqsesi_la-rwl.lo \ - libqsesi_la-sck.lo libqsesi_la-sio.lo libqsesi_la-task.lo \ - libqsesi_la-thr.lo libqsesi_la-tio.lo + libqsesi_la-sck.lo libqsesi_la-sinfo.lo libqsesi_la-sio.lo \ + libqsesi_la-task.lo libqsesi_la-thr.lo libqsesi_la-tio.lo libqsesi_la_OBJECTS = $(am_libqsesi_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -161,8 +161,10 @@ libqsesi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libqsesi_la_CFLAGS) \ $(CFLAGS) $(libqsesi_la_LDFLAGS) $(LDFLAGS) -o $@ libqsesixx_la_DEPENDENCIES = -am__libqsesixx_la_SOURCES_DIST = SocketAddress.cpp Socket.cpp -@ENABLE_CXX_TRUE@am_libqsesixx_la_OBJECTS = SocketAddress.lo Socket.lo +am__libqsesixx_la_SOURCES_DIST = AppRoot.cpp SocketAddress.cpp \ + Socket.cpp +@ENABLE_CXX_TRUE@am_libqsesixx_la_OBJECTS = AppRoot.lo \ +@ENABLE_CXX_TRUE@ SocketAddress.lo Socket.lo libqsesixx_la_OBJECTS = $(am_libqsesixx_la_OBJECTS) libqsesixx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -471,6 +473,7 @@ libqsesi_la_SOURCES = \ pio.c \ rwl.c \ sck.c \ + sinfo.c \ sio.c \ task.c \ thr.c \ @@ -481,6 +484,7 @@ libqsesi_la_CFLAGS = $(PTHREAD_CFLAGS) libqsesi_la_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined libqsesi_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) $(SSL_LIBS) @ENABLE_CXX_TRUE@libqsesixx_la_SOURCES = \ +@ENABLE_CXX_TRUE@ AppRoot.cpp \ @ENABLE_CXX_TRUE@ SocketAddress.cpp \ @ENABLE_CXX_TRUE@ Socket.cpp @@ -567,6 +571,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AppRoot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Socket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-pro.Plo@am__quote@ @@ -596,6 +601,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-pio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-rwl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-sck.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-sinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-sio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-task.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-thr.Plo@am__quote@ @@ -811,6 +817,13 @@ libqsesi_la-sck.lo: sck.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-sck.lo `test -f 'sck.c' || echo '$(srcdir)/'`sck.c +libqsesi_la-sinfo.lo: sinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-sinfo.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-sinfo.Tpo -c -o libqsesi_la-sinfo.lo `test -f 'sinfo.c' || echo '$(srcdir)/'`sinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-sinfo.Tpo $(DEPDIR)/libqsesi_la-sinfo.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sinfo.c' object='libqsesi_la-sinfo.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-sinfo.lo `test -f 'sinfo.c' || echo '$(srcdir)/'`sinfo.c + libqsesi_la-sio.lo: sio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-sio.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-sio.Tpo -c -o libqsesi_la-sio.lo `test -f 'sio.c' || echo '$(srcdir)/'`sio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-sio.Tpo $(DEPDIR)/libqsesi_la-sio.Plo diff --git a/qse/lib/si/pio.c b/qse/lib/si/pio.c index 03e278a8..26ffb5ba 100644 --- a/qse/lib/si/pio.c +++ b/qse/lib/si/pio.c @@ -25,6 +25,7 @@ */ #include +#include #include #include "../cmn/mem-prv.h" @@ -374,145 +375,6 @@ static QSE_INLINE int is_fd_valid_and_nocloexec (int fd) return !(flags & FD_CLOEXEC)? 1: 0; } -static int close_unneeded_fds_using_proc (int* excepts, qse_size_t count) -{ - QSE_DIR* d; - - /* will getting the highest file descriptor be faster than - * attempting to close any files descriptors less than the - * system limit? */ - - d = QSE_OPENDIR (QSE_MT("/proc/self/fd")); - if (!d) - { - qse_mchar_t buf[64]; - qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID()); - d = QSE_OPENDIR (buf); - #if !defined(_SCO_DS) - /* on SCO OpenServer, a range of file descriptors starting from 0 are - * listed under /dev/fd regardless of opening state. And some high - * numbered descriptors are not listed all. not reliable */ - - if (!d) d = QSE_OPENDIR (QSE_MT("/dev/fd")); /* Darwin, FreeBSD */ - #endif - } - - if (d) - { - qse_dirent_t* de; - while ((de = QSE_READDIR (d))) - { - qse_long_t l; - const qse_mchar_t* endptr; - - if (de->d_name[0] == QSE_MT('.')) continue; - - QSE_MBSTONUM (l, de->d_name, &endptr, 10); - if (*endptr == QSE_MT('\0')) - { - int fd = (int)l; - if ((qse_long_t)fd == l && fd != QSE_DIRFD(d) && fd > 2) - { - qse_size_t i; - - for (i = 0; i < count; i++) - { - if (fd == excepts[i]) goto skip_close; - } - - QSE_CLOSE (fd); - - skip_close: - ; - } - } - } - - QSE_CLOSEDIR (d); - return 0; - } - - return -1; -} - -static int get_highest_fd (void) -{ -#if defined(HAVE_GETRLIMIT) - struct rlimit rlim; -#endif - int fd = -1; - QSE_DIR* d; - -#if defined(F_MAXFD) - fd = QSE_FCNTL (0, F_MAXFD, 0); - if (fd >= 0) return fd; -#endif - - /* will getting the highest file descriptor be faster than - * attempting to close any files descriptors less than the - * system limit? */ - - d = QSE_OPENDIR (QSE_MT("/proc/self/fd")); - if (!d) - { - qse_mchar_t buf[64]; - qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID()); - d = QSE_OPENDIR (buf); - if (!d) d = QSE_OPENDIR (QSE_MT("/dev/fd")); /* Darwin, FreeBSD */ - } - - if (d) - { - int maxfd = -1; - qse_dirent_t* de; - while ((de = QSE_READDIR (d))) - { - qse_long_t l; - const qse_mchar_t* endptr; - - if (de->d_name[0] == QSE_MT('.')) continue; - - QSE_MBSTONUM (l, de->d_name, &endptr, 10); - if (*endptr == QSE_MT('\0')) - { - fd = (int)l; - if ((qse_long_t)fd == l && fd != QSE_DIRFD(d)) - { - if (fd > maxfd) maxfd = fd; - } - } - } - - QSE_CLOSEDIR (d); - return maxfd; - } - -/* TODO: should i also use getdtablesize() if available? */ - -#if defined(HAVE_GETRLIMIT) - if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 || - rlim.rlim_max == RLIM_INFINITY) - { - #if defined(HAVE_SYSCONF) - fd = sysconf (_SC_OPEN_MAX); - #endif - } - else fd = rlim.rlim_max; -#elif defined(HAVE_SYSCONF) - fd = sysconf (_SC_OPEN_MAX); -#endif - if (fd <= -1) fd = 1024; /* fallback */ - - /* F_MAXFD is the highest fd. but RLIMIT_NOFILE and - * _SC_OPEN_MAX returnes the maximum number of file - * descriptors. make adjustment */ - if (fd > 0) fd--; - - - return fd; -} - - static qse_pio_pid_t standard_fork_and_exec (qse_pio_t* pio, int pipes[], param_t* param, qse_env_t* env) { qse_pio_pid_t pid; @@ -537,17 +399,17 @@ static qse_pio_pid_t standard_fork_and_exec (qse_pio_t* pio, int pipes[], param_ if (!(pio->flags & QSE_PIO_NOCLOEXEC)) { - if (close_unneeded_fds_using_proc (pipes, 6) <= -1) + if (qse_close_open_fds_using_proc (pipes, 6) <= -1) { - int fd = get_highest_fd (); + int fd = qse_get_highest_fd (); /* close all other unknown open handles except * stdin/out/err and the pipes. */ while (fd > 2) { if (fd != pipes[0] && fd != pipes[1] && - fd != pipes[2] && fd != pipes[3] && - fd != pipes[4] && fd != pipes[5]) + fd != pipes[2] && fd != pipes[3] && + fd != pipes[4] && fd != pipes[5]) { QSE_CLOSE (fd); } @@ -1571,7 +1433,7 @@ create_process: if (!(flags & QSE_PIO_NOCLOEXEC)) { - int fd = get_highest_fd (); + int fd = qse_get_highest_fd (); while (fd > 2) { if (fd != handle[0] && fd != handle[1] && @@ -1651,7 +1513,7 @@ create_process: /* prepare some data before vforking for vfork limitation. * the child in vfork should not make function calls or * change data shared with the parent. */ - if (!(flags & QSE_PIO_NOCLOEXEC)) highest_fd = get_highest_fd (); + if (!(flags & QSE_PIO_NOCLOEXEC)) highest_fd = qse_get_highest_fd (); envarr = env? qse_env_getarr(env): environ; QSE_SYSCALL0 (pid, SYS_vfork); @@ -1673,7 +1535,7 @@ create_process: if (!(flags & QSE_PIO_NOCLOEXEC)) { - /* cannot call close_unneeded_fds_using_proc() in the vfork() context */ + /* cannot call qse_close_open_fds_using_proc() in the vfork() context */ int fd = highest_fd; diff --git a/qse/lib/si/sinfo.c b/qse/lib/si/sinfo.c new file mode 100644 index 00000000..f9096a8c --- /dev/null +++ b/qse/lib/si/sinfo.c @@ -0,0 +1,166 @@ +/* + * $Id$ + * + Copyright (c) 2006-2014 Chung, Hyung-Hwan. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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. + */ + +#include +#include +#include "../cmn/syscall.h" + +int qse_get_highest_fd (void) +{ +#if defined(HAVE_GETRLIMIT) + struct rlimit rlim; +#endif + int fd = -1; + QSE_DIR* d; + +#if defined(F_MAXFD) + fd = QSE_FCNTL (0, F_MAXFD, 0); + if (fd >= 0) return fd; +#endif + + /* will getting the highest file descriptor be faster than + * attempting to close any files descriptors less than the + * system limit? */ + + d = QSE_OPENDIR (QSE_MT("/proc/self/fd")); + if (!d) + { + qse_mchar_t buf[64]; + qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID()); + d = QSE_OPENDIR (buf); + if (!d) d = QSE_OPENDIR (QSE_MT("/dev/fd")); /* Darwin, FreeBSD */ + } + + if (d) + { + int maxfd = -1; + qse_dirent_t* de; + while ((de = QSE_READDIR (d))) + { + qse_long_t l; + const qse_mchar_t* endptr; + + if (de->d_name[0] == QSE_MT('.')) continue; + + QSE_MBSTONUM (l, de->d_name, &endptr, 10); + if (*endptr == QSE_MT('\0')) + { + fd = (int)l; + if ((qse_long_t)fd == l && fd != QSE_DIRFD(d)) + { + if (fd > maxfd) maxfd = fd; + } + } + } + + QSE_CLOSEDIR (d); + return maxfd; + } + +/* TODO: should i also use getdtablesize() if available? */ + +#if defined(HAVE_GETRLIMIT) + if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 || + rlim.rlim_max == RLIM_INFINITY) + { + #if defined(HAVE_SYSCONF) + fd = sysconf (_SC_OPEN_MAX); + #endif + } + else fd = rlim.rlim_max; +#elif defined(HAVE_SYSCONF) + fd = sysconf (_SC_OPEN_MAX); +#endif + if (fd <= -1) fd = 1024; /* fallback */ + + /* F_MAXFD is the highest fd. but RLIMIT_NOFILE and + * _SC_OPEN_MAX returnes the maximum number of file + * descriptors. make adjustment */ + if (fd > 0) fd--; + + return fd; +} + +int qse_close_open_fds_using_proc (int* excepts, qse_size_t count) +{ + QSE_DIR* d; + + /* will getting the highest file descriptor be faster than + * attempting to close any files descriptors less than the + * system limit? */ + + d = QSE_OPENDIR (QSE_MT("/proc/self/fd")); + if (!d) + { + qse_mchar_t buf[64]; + qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID()); + d = QSE_OPENDIR (buf); + #if !defined(_SCO_DS) + /* on SCO OpenServer, a range of file descriptors starting from 0 are + * listed under /dev/fd regardless of opening state. And some high + * numbered descriptors are not listed. not reliable */ + + if (!d) d = QSE_OPENDIR (QSE_MT("/dev/fd")); /* Darwin, FreeBSD */ + #endif + } + + if (d) + { + qse_dirent_t* de; + while ((de = QSE_READDIR (d))) + { + qse_long_t l; + const qse_mchar_t* endptr; + + if (de->d_name[0] == QSE_MT('.')) continue; + + QSE_MBSTONUM (l, de->d_name, &endptr, 10); + if (*endptr == QSE_MT('\0')) + { + int fd = (int)l; + if ((qse_long_t)fd == l && fd != QSE_DIRFD(d) && fd > 2) + { + qse_size_t i; + + for (i = 0; i < count; i++) + { + if (fd == excepts[i]) goto skip_close; + } + + QSE_CLOSE (fd); + + skip_close: + ; + } + } + } + + QSE_CLOSEDIR (d); + return 0; + } + + return -1; +}