⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uxprocess.cpp

📁 Advanced UNIX Programming is the long-awaited (19 years!) update to the 1985 original. Maybe "update
💻 CPP
字号:
/*	Copyright 2003 by Marc J. Rochkind. All rights reserved.	May be copied only for purposes and under conditions described	on the Web page www.basepath.com/aup/copyright.htm.	The Example Files are provided "as is," without any warranty;	without even the implied warranty of merchantability or fitness	for a particular purpose. The author and his publisher are not	responsible for any damages, direct or incidental, resulting	from the use or non-use of these Example Files.	The Example Files may contain defects, and some contain deliberate	coding mistakes that were included for educational reasons.	You are responsible for determining if and how the Example Files	are to be used.*/#ifdef SOLARIS// needed for setegid and seteuid#define __EXTENSIONS__#endif/*	Need to prevent GNU from using the wrong prototype for functions declared in	sys/resource.h (see comment there). As sys/wait.h (included by defs.h) brings	in this include (on GNU systems, anyway), there is a special symbol (AUP2_SKIP_WAIT)	used in defs.h to suppress that include. Also, we should not have to undef __USE_GNU	(I think), we seem to have to do that as well.		(It would have been much better if the GNU folks had not tried to improve things!)*/#define AUP2_SKIP_WAIT#include "defs.h"#ifdef _GNU_SOURCE#define _GNU_SOURCE_WAS_DEFINED#undef _GNU_SOURCE#undef __USE_GNU#endif#include <sys/resource.h>#ifdef _GNU_SOURCE_WAS_DEFINED#define _GNU_SOURCE#undef _GNU_SOURCE_WAS_DEFINED#endif#include <sys/wait.h> // now it is OK to bring it in#include "ux.hpp" // and now everything else can come inusing namespace Ux;/**	Calls ::atexit.*//* static */ void Process::atexit(void (*fcn)(void)){	errno = 0; // SUS doesn't say it's set on error	if (::atexit(fcn) != 0)		throw Error(errno);}/**	Calls ::chdir.*//* static */ void Process::chdir(const char *path){	if (::chdir(path) == -1)		throw Error(errno);}/**	Calls ::fchdir.*//* static */ void Process::chdir(int fd){	if (::fchdir(fd) == -1)		throw Error(errno);}/**	Calls ::chroot.*//* static */ void Process::chroot(const char *path){	if (::chroot(path) == -1)		throw Error(errno);}/**	Calls ::clock.*//* static */ clock_t Process::clock(void){	clock_t c;	errno = 0;	if ((c = ::clock()) == -1) {		if (errno == 0)			throw Error(EINVAL);		else			throw Error(errno);	}	return c;}/**	Calls ::execvp after building a vector from the arguments. (Not feasible to call ::execlp,	as there's no portable way to pass it the arguments as a list.)*//* static */ void Process::execlp(const char *file, const char *arg0, ...){	va_list ap;	int count;	va_start(ap, arg0);	for (count = 1; va_arg(ap, char *) != NULL; count++)		;	va_end(ap);	 char **argv = new  char*[count + 1];	if (argv == NULL)		throw Error(ENOMEM);	va_start(ap, arg0);	argv[0] = (char *)arg0;	for (count = 1; (argv[count] = va_arg(ap, char *)) != NULL; count++)		;	va_end(ap);	(void)::execvp(file, argv);	delete [] argv;	throw Error(errno);}/**	Calls ::execvp, first setting the global environ to the argument if it's non-NULL.	environ is restored if the call fails. Not thread safe, as setting and re-setting of	environ isn't protected with a mutex. (It's not that important for an exec call to be	thread safe, since calling it with more than one thread active is not good practice anyway.)*//* static */ void Process::execvpe(const char *file, char *const argv[], char *const *envv = NULL){	extern char **environ;	char **environ_save = environ;	if (envv != NULL)		environ = (char **)envv;	(void)execvp(file, argv);	environ = environ_save;	throw Error(errno);}/**	Calls ::fork. Returns a Process, which is automatically converted to a pid_t if necessary.*//* static */ Process Process::fork(void){	pid_t rtn_pid;		if ((rtn_pid = ::fork()) == -1)		throw Error(errno);	return Process(rtn_pid);}/**	Calls ::getcwd. Dir argument must have space allocated with File::alloc,	or at least the size and path members set properly.*//* static */ void Process::getcwd(Dir& d){	if (d.get_size() < 0)		throw Error(ENOMEM);	// overriding const -- user better have supplied buffer!	if (::getcwd((char *)(const char *)d, d.get_size()) == NULL)		throw(errno);}/**	Calls ::getenv. Does not throw error; returns NULL if not found.*//* static */ char* Process::getenv(const char *var){	return ::getenv(var);}/**	Calls ::getpgid.*//* static */ pid_t Process::getpgid(pid_t pid){	pid_t rtn_pid;	if ((rtn_pid = ::getpgid(pid)) == -1)		throw Error(errno);	return rtn_pid;}/**	Calls ::getrlimit.*//* static */ void Process::getrlimit(int resource, struct rlimit *rlp){	if (::getrlimit(resource, rlp) == -1)		throw Error(errno);}/**	Calls ::getrusage.*//* static */ void Process::getrusage(int who, struct rusage *r_usage){	if (::getrusage(who, r_usage) == -1)		throw Error(errno);}/**	Calls ::getsid, for this process. getsid(0) (getsid of calling process) not	implemented and not needed, since a Process is initialized to the calling process	by default.*/pid_t Process::getsid(void){	pid_t rtn_pid;	if ((rtn_pid = ::getsid(pid)) == -1)		throw Error(errno);	return rtn_pid;}/**	Calls ::kill.*//* static */ void Process::kill(pid_t pid, int signum){	if (::kill(pid, signum) == -1)		throw Error(errno);}/**	Calls ::nice.*//* static */ void Process::nice(int incr){	if (::nice(incr) == -1)		throw Error(errno);}/**	Calls ::pause.*//* static */ void Process::pause(void){	if (::pause() == -1 && errno != EINTR)		throw Error(errno);}/**	Calls ::putenv.*//* static */ void Process::putenv(char *string){	if (::putenv(string) != 0)		throw Error(errno);}/**	Calls ::setegid.*//* static */ void Process::setegid(gid_t gid){	if (::setegid(gid) == -1)		throw Error(errno);}/**	Calls ::setenv.*//* static */ void Process::setenv(const char *var, const char *val, int overwrite){#if _XOPEN_VERSION >= 600 || defined(FREEBSD) || defined(LINUX)	if (::setenv(var, val, overwrite) == -1)		throw Error(errno);#else	throw Error(ENOSYS);#endif}/**	Calls ::seteuid.*//* static */ void Process::seteuid(uid_t uid){	if (::seteuid(uid) == -1)		throw Error(errno);}/**	Calls ::setgid.*//* static */ void Process::setgid(gid_t gid){	if (::setgid(gid) == -1)		throw Error(errno);}/**	Calls ::setpgid.*//* static */ void Process::setpgid(pid_t pid, pid_t pgid){	if (::setpgid(pid, pgid) == -1)		throw Error(errno);}/**	Calls ::setrlimit.*//* static */ void Process::setrlimit(int resource, const struct rlimit *rlp){	if (::setrlimit(resource, rlp) == -1)		throw Error(errno);}/**	Calls ::setsid.*//* static */ pid_t Process::setsid(void){	pid_t rtn_pid;	if ((rtn_pid = ::setsid()) == -1)		throw Error(errno);	return rtn_pid;}/**	Calls ::setuid.*//* static */ void Process::setuid(uid_t uid){	if (::setuid(uid) == -1)		throw Error(errno);}/**	Calls ::sigaction.*//* static */ void Process::sigaction(int signum, const struct sigaction *act, struct sigaction *oact){	if (::sigaction(signum, act, oact) == -1)		throw Error(errno);}/**	Calls ::sigaltstack.*//* static */ void Process::sigaltstack(const stack_t *stack, stack_t *ostack){	if (::sigaltstack(stack, ostack) == -1)		throw Error(errno);}/**	Calls ::siginterrupt.*//* static */ void Process::siginterrupt(int signum, int on){	if (::siginterrupt(signum, on) == -1)		throw Error(errno);}/**	Calls ::sigprocmask.*//* static */ void Process::sigprocmask(int how, const sigset_t *set, sigset_t *oset){	if (::sigprocmask(how, set, oset) == -1)		throw Error(errno);}/**	Calls ::sigqueue.*/void Process::sigqueue(int signum, const union sigval value){#ifdef _POSIX_REALTIME_SIGNALS	if (::sigqueue(pid, signum, value) == -1)		throw Error(errno);#else	throw Error(ENOSYS);#endif}/**	Calls ::sigsuspend.*//* static */ void Process::sigsuspend(const sigset_t *sigmask){	if (::sigsuspend(sigmask) == -1)		throw Error(errno);}/* Returns -1 on error, always (sets errno) *//**	Calls ::sigtimedwait.*//* static */ int Process::sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *ts){#ifdef _POSIX_REALTIME_SIGNALS	int r;	if ((r = ::sigtimedwait(set, info, ts)) == -1)		throw Error(errno);	return r;#else	throw Error(ENOSYS);#endif}/* Returns signal number or -1 on error (sets errno) *//**	Calls ::sigwait.*//* static */ void Process::sigwait(const sigset_t *set, int *signum){#if _XOPEN_VERSION >= 500	if (::sigwait(set, signum) == -1)		throw Error(errno);#else	throw Error(ENOSYS);#endif}/* Returns 0 on success or error number on error *//**	Calls ::sigwaitinfo.*//* static */ int Process::sigwaitinfo(const sigset_t *set, siginfo_t *info){#ifdef _POSIX_REALTIME_SIGNALS	int r;	if ((r = ::sigwaitinfo(set, info)) == -1)		throw Error(errno);	return r;#else	throw Error(ENOSYS);#endif}/* Returns signal number or -1 on error (sets errno) *//**	Calls ::system.*//* static */ int Process::system(const char *command){	int n;	if ((n = ::system(command)) == -1)		throw Error(errno);	return n;}/**	Calls ::times.*//* static */ clock_t Process::times(struct tms *buffer){	clock_t c;	if ((c = ::times(buffer)) == -1)		throw Error(errno);	return c;}/**	Calls ::unsetenv.*//* static */ void Process::unsetenv(const char *var){#if _XOPEN_VERSION >= 600	if (::unsetenv(var) == -1)		throw Error(errno);#elif defined(FREEBSD) || defined(LINUX)	::unsetenv(var);#else	throw Error(ENOSYS);#endif}/**	Calls ::waitid if it's supported. Otherwise throws ENOSYS.*//* static */ void Process::waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options){#ifdef _XOPEN_UNIX	if (::waitid(idtype, id, infop, options) == -1)		throw Error(errno);#else		throw Error(ENOSYS);#endif}/**	Calls ::waitpid. Use the inline version if you want to operate on the	Process object's process ID.*//* static */ pid_t Process::waitpid(pid_t pid, ExitStatus *statusp, int options = 0){	pid_t rtn_pid;	int status;	if ((rtn_pid = ::waitpid(pid, &status, options)) == -1)		throw Error(errno);	if (statusp != NULL)		statusp->set(status);	return rtn_pid;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -