added qse_get_highest_fd(), qse_close_open_fds_using_proc()
added QSE::AppRoot::daemonize()
This commit is contained in:
		
							
								
								
									
										56
									
								
								qse/include/qse/si/AppRoot.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								qse/include/qse/si/AppRoot.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -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 <qse/Types.hpp> | ||||||
|  | #include <qse/Uncopyable.hpp> | ||||||
|  |  | ||||||
|  | ///////////////////////////////// | ||||||
|  | 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 | ||||||
| @ -19,6 +19,7 @@ pkginclude_HEADERS = \ | |||||||
| 	pio.h  \ | 	pio.h  \ | ||||||
| 	rwl.h \ | 	rwl.h \ | ||||||
| 	sck.h \ | 	sck.h \ | ||||||
|  | 	sinfo.h \ | ||||||
| 	sio.h  \ | 	sio.h  \ | ||||||
| 	task.h \ | 	task.h \ | ||||||
| 	thr.h \ | 	thr.h \ | ||||||
| @ -26,6 +27,7 @@ pkginclude_HEADERS = \ | |||||||
|  |  | ||||||
| if ENABLE_CXX | if ENABLE_CXX | ||||||
| pkginclude_HEADERS += \ | pkginclude_HEADERS += \ | ||||||
|  | 	AppRoot.hpp \ | ||||||
| 	SocketAddress.hpp \ | 	SocketAddress.hpp \ | ||||||
| 	Socket.hpp | 	Socket.hpp | ||||||
| endif | endif | ||||||
|  | |||||||
| @ -88,6 +88,7 @@ POST_UNINSTALL = : | |||||||
| build_triplet = @build@ | build_triplet = @build@ | ||||||
| host_triplet = @host@ | host_triplet = @host@ | ||||||
| @ENABLE_CXX_TRUE@am__append_1 = \ | @ENABLE_CXX_TRUE@am__append_1 = \ | ||||||
|  | @ENABLE_CXX_TRUE@	AppRoot.hpp \ | ||||||
| @ENABLE_CXX_TRUE@	SocketAddress.hpp \ | @ENABLE_CXX_TRUE@	SocketAddress.hpp \ | ||||||
| @ENABLE_CXX_TRUE@	Socket.hpp | @ENABLE_CXX_TRUE@	Socket.hpp | ||||||
|  |  | ||||||
| @ -130,8 +131,8 @@ am__can_run_installinfo = \ | |||||||
|   esac |   esac | ||||||
| am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \ | 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 \ | 	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 \ | 	nwio.h pio.h rwl.h sck.h sinfo.h sio.h task.h thr.h tio.h \ | ||||||
| 	SocketAddress.hpp Socket.hpp | 	AppRoot.hpp SocketAddress.hpp Socket.hpp | ||||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||||
| am__vpath_adj = case $$p in \ | am__vpath_adj = case $$p in \ | ||||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||||
| @ -366,7 +367,7 @@ top_builddir = @top_builddir@ | |||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| pkginclude_HEADERS = aio.h aio-pro.h aio-sck.h cnd.h dir.h fio.h fs.h \ | 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 \ | 	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 | all: all-am | ||||||
|  |  | ||||||
| .SUFFIXES: | .SUFFIXES: | ||||||
|  | |||||||
							
								
								
									
										49
									
								
								qse/include/qse/si/sinfo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								qse/include/qse/si/sinfo.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 <qse/types.h> | ||||||
|  | #include <qse/macros.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #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 | ||||||
| @ -69,6 +69,9 @@ | |||||||
| #if defined(HAVE_DIRENT_H) | #if defined(HAVE_DIRENT_H) | ||||||
| #	include <dirent.h> | #	include <dirent.h> | ||||||
| #endif | #endif | ||||||
|  | #if defined(HAVE_SYS_IOCTL_H) | ||||||
|  | #	include <sys/ioctl.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #if defined(QSE_USE_SYSCALL) && defined(HAVE_SYS_SYSCALL_H) | #if defined(QSE_USE_SYSCALL) && defined(HAVE_SYS_SYSCALL_H) | ||||||
| #	include <sys/syscall.h> | #	include <sys/syscall.h> | ||||||
| @ -214,6 +217,24 @@ | |||||||
| #	define QSE_GETEGID() getegid() | #	define QSE_GETEGID() getegid() | ||||||
| #endif | #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) | #if defined(SYS_gettimeofday) && defined(QSE_USE_SYSCALL) | ||||||
| #	define QSE_GETTIMEOFDAY(tv,tz) syscall(SYS_gettimeofday,tv,tz) | #	define QSE_GETTIMEOFDAY(tv,tz) syscall(SYS_gettimeofday,tv,tz) | ||||||
| #else | #else | ||||||
| @ -250,6 +271,12 @@ | |||||||
| #	define QSE_SETRLIMIT(res,lim) setrlimit(res,lim) | #	define QSE_SETRLIMIT(res,lim) setrlimit(res,lim) | ||||||
| #endif | #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 ===== */ | /* ===== FILE SYSTEM CALLS ===== */ | ||||||
|  |  | ||||||
| @ -378,6 +405,12 @@ | |||||||
| #	define QSE_RENAME(oldpath,newpath) rename(oldpath,newpath) | #	define QSE_RENAME(oldpath,newpath) rename(oldpath,newpath) | ||||||
| #endif | #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) | #if defined(SYS_mkdir) && defined(QSE_USE_SYSCALL) | ||||||
| #	define QSE_MKDIR(path,mode) syscall(SYS_mkdir,path,mode) | #	define QSE_MKDIR(path,mode) syscall(SYS_mkdir,path,mode) | ||||||
| #else | #else | ||||||
| @ -390,6 +423,12 @@ | |||||||
| #	define QSE_RMDIR(path) rmdir(path) | #	define QSE_RMDIR(path) rmdir(path) | ||||||
| #endif | #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) | #if defined(SYS_symlink) && defined(QSE_USE_SYSCALL) | ||||||
| #	define QSE_SYMLINK(oldpath,newpath) syscall(SYS_symlink,oldpath,newpath) | #	define QSE_SYMLINK(oldpath,newpath) syscall(SYS_symlink,oldpath,newpath) | ||||||
| #else | #else | ||||||
|  | |||||||
							
								
								
									
										153
									
								
								qse/lib/si/AppRoot.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								qse/lib/si/AppRoot.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -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 <qse/si/AppRoot.hpp> | ||||||
|  | #include <qse/si/sinfo.h> | ||||||
|  | #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) | ||||||
|  | ///////////////////////////////// | ||||||
| @ -38,6 +38,7 @@ libqsesi_la_SOURCES =  \ | |||||||
| 	pio.c  \ | 	pio.c  \ | ||||||
| 	rwl.c \ | 	rwl.c \ | ||||||
| 	sck.c \ | 	sck.c \ | ||||||
|  | 	sinfo.c \ | ||||||
| 	sio.c  \ | 	sio.c  \ | ||||||
| 	task.c \ | 	task.c \ | ||||||
| 	thr.c \ | 	thr.c \ | ||||||
| @ -51,6 +52,7 @@ libqsesi_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) $(SSL_LIBS) | |||||||
| if ENABLE_CXX | if ENABLE_CXX | ||||||
| lib_LTLIBRARIES += libqsesixx.la | lib_LTLIBRARIES += libqsesixx.la | ||||||
| libqsesixx_la_SOURCES = \ | libqsesixx_la_SOURCES = \ | ||||||
|  | 	AppRoot.cpp \ | ||||||
| 	SocketAddress.cpp \ | 	SocketAddress.cpp \ | ||||||
| 	Socket.cpp | 	Socket.cpp | ||||||
| libqsesixx_la_LDFLAGS = -L. -L../cmn -version-info 1:0:0 -no-undefined | libqsesixx_la_LDFLAGS = -L. -L../cmn -version-info 1:0:0 -no-undefined | ||||||
|  | |||||||
| @ -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-nwad.lo libqsesi_la-nwad-skad.lo \ | ||||||
| 	libqsesi_la-nwif.lo libqsesi_la-nwif-cfg.lo \ | 	libqsesi_la-nwif.lo libqsesi_la-nwif-cfg.lo \ | ||||||
| 	libqsesi_la-nwio.lo libqsesi_la-pio.lo libqsesi_la-rwl.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-sck.lo libqsesi_la-sinfo.lo libqsesi_la-sio.lo \ | ||||||
| 	libqsesi_la-thr.lo libqsesi_la-tio.lo | 	libqsesi_la-task.lo libqsesi_la-thr.lo libqsesi_la-tio.lo | ||||||
| libqsesi_la_OBJECTS = $(am_libqsesi_la_OBJECTS) | libqsesi_la_OBJECTS = $(am_libqsesi_la_OBJECTS) | ||||||
| AM_V_lt = $(am__v_lt_@AM_V@) | AM_V_lt = $(am__v_lt_@AM_V@) | ||||||
| am__v_lt_ = $(am__v_lt_@AM_DEFAULT_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) \ | 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libqsesi_la_CFLAGS) \ | ||||||
| 	$(CFLAGS) $(libqsesi_la_LDFLAGS) $(LDFLAGS) -o $@ | 	$(CFLAGS) $(libqsesi_la_LDFLAGS) $(LDFLAGS) -o $@ | ||||||
| libqsesixx_la_DEPENDENCIES = | libqsesixx_la_DEPENDENCIES = | ||||||
| am__libqsesixx_la_SOURCES_DIST = SocketAddress.cpp Socket.cpp | am__libqsesixx_la_SOURCES_DIST = AppRoot.cpp SocketAddress.cpp \ | ||||||
| @ENABLE_CXX_TRUE@am_libqsesixx_la_OBJECTS = SocketAddress.lo Socket.lo | 	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_OBJECTS = $(am_libqsesixx_la_OBJECTS) | ||||||
| libqsesixx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ | libqsesixx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ | ||||||
| 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ | 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ | ||||||
| @ -471,6 +473,7 @@ libqsesi_la_SOURCES = \ | |||||||
| 	pio.c  \ | 	pio.c  \ | ||||||
| 	rwl.c \ | 	rwl.c \ | ||||||
| 	sck.c \ | 	sck.c \ | ||||||
|  | 	sinfo.c \ | ||||||
| 	sio.c  \ | 	sio.c  \ | ||||||
| 	task.c \ | 	task.c \ | ||||||
| 	thr.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_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined | ||||||
| libqsesi_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) $(SSL_LIBS) | libqsesi_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) $(SSL_LIBS) | ||||||
| @ENABLE_CXX_TRUE@libqsesixx_la_SOURCES = \ | @ENABLE_CXX_TRUE@libqsesixx_la_SOURCES = \ | ||||||
|  | @ENABLE_CXX_TRUE@	AppRoot.cpp \ | ||||||
| @ENABLE_CXX_TRUE@	SocketAddress.cpp \ | @ENABLE_CXX_TRUE@	SocketAddress.cpp \ | ||||||
| @ENABLE_CXX_TRUE@	Socket.cpp | @ENABLE_CXX_TRUE@	Socket.cpp | ||||||
|  |  | ||||||
| @ -567,6 +571,7 @@ mostlyclean-compile: | |||||||
| distclean-compile: | distclean-compile: | ||||||
| 	-rm -f *.tab.c | 	-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)/Socket.Plo@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.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@ | @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-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-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-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-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-task.Plo@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-thr.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@ | @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 | @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 | 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_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 | @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-sio.Tpo $(DEPDIR)/libqsesi_la-sio.Plo | ||||||
|  | |||||||
							
								
								
									
										154
									
								
								qse/lib/si/pio.c
									
									
									
									
									
								
							
							
						
						
									
										154
									
								
								qse/lib/si/pio.c
									
									
									
									
									
								
							| @ -25,6 +25,7 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <qse/si/pio.h> | #include <qse/si/pio.h> | ||||||
|  | #include <qse/si/sinfo.h> | ||||||
| #include <qse/cmn/mbwc.h> | #include <qse/cmn/mbwc.h> | ||||||
| #include "../cmn/mem-prv.h" | #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; | 	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) | 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; | 	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 (!(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  | 				/* close all other unknown open handles except  | ||||||
| 				 * stdin/out/err and the pipes. */ | 				 * stdin/out/err and the pipes. */ | ||||||
| 				while (fd > 2) | 				while (fd > 2) | ||||||
| 				{ | 				{ | ||||||
| 					if (fd != pipes[0] && fd != pipes[1] && | 					if (fd != pipes[0] && fd != pipes[1] && | ||||||
| 						fd != pipes[2] && fd != pipes[3] && | 					    fd != pipes[2] && fd != pipes[3] && | ||||||
| 						fd != pipes[4] && fd != pipes[5])  | 					    fd != pipes[4] && fd != pipes[5])  | ||||||
| 					{ | 					{ | ||||||
| 						QSE_CLOSE (fd); | 						QSE_CLOSE (fd); | ||||||
| 					} | 					} | ||||||
| @ -1571,7 +1433,7 @@ create_process: | |||||||
|  |  | ||||||
| 		if (!(flags & QSE_PIO_NOCLOEXEC)) | 		if (!(flags & QSE_PIO_NOCLOEXEC)) | ||||||
| 		{ | 		{ | ||||||
| 			int fd = get_highest_fd (); | 			int fd = qse_get_highest_fd (); | ||||||
| 			while (fd > 2) | 			while (fd > 2) | ||||||
| 			{ | 			{ | ||||||
| 				if (fd != handle[0] && fd != handle[1] && | 				if (fd != handle[0] && fd != handle[1] && | ||||||
| @ -1651,7 +1513,7 @@ create_process: | |||||||
| 		/* prepare some data before vforking for vfork limitation. | 		/* prepare some data before vforking for vfork limitation. | ||||||
| 		 * the child in vfork should not make function calls or  | 		 * the child in vfork should not make function calls or  | ||||||
| 		 * change data shared with the parent. */ | 		 * 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; | 		envarr = env? qse_env_getarr(env): environ; | ||||||
|  |  | ||||||
| 		QSE_SYSCALL0 (pid, SYS_vfork); | 		QSE_SYSCALL0 (pid, SYS_vfork); | ||||||
| @ -1673,7 +1535,7 @@ create_process: | |||||||
|  |  | ||||||
| 			if (!(flags & QSE_PIO_NOCLOEXEC)) | 			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; | 				int fd = highest_fd; | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										166
									
								
								qse/lib/si/sinfo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								qse/lib/si/sinfo.c
									
									
									
									
									
										Normal file
									
								
							| @ -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 <qse/si/sinfo.h> | ||||||
|  | #include <qse/cmn/str.h> | ||||||
|  | #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; | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user