📄 process.cpp
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by// the GNU General Public License. //// This exception applies only to the code released under the name GNU// Common C++. If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include <cc++/config.h>#include <cc++/export.h>#include <cc++/thread.h>#include <cc++/process.h>#include <cc++/strchar.h>#include <cstdlib>#include <cstdio>#include <cerrno>#include <csignal>#ifdef MACOSX#undef _POSIX_PRIORITY_SCHEDULING#endif#ifndef WIN32#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#include <pwd.h>#include <grp.h>#ifdef SIGTSTP#include <sys/file.h>#include <sys/ioctl.h>#endif#ifndef _PATH_TTY#define _PATH_TTY "/dev/tty"#endif#endif#ifdef WIN32#include <process.h>#include <stdio.h>#endif#ifdef CCXX_NAMESPACESnamespace ost {#endifstatic char *_pUser = NULL;static char *_pHome = NULL;#ifdef WIN32static SYSTEM_INFO sysinfo;static LPSYSTEM_INFO lpSysInfo = NULL;static void init_sysinfo(void){ if(!lpSysInfo) { lpSysInfo = &sysinfo; memset(&sysinfo, 0, sizeof(sysinfo)); GetSystemInfo(lpSysInfo); }}const char *Process::getUser(void){ static char userid[65]; DWORD length = sizeof(userid); if(GetUserName(userid, &length)) return userid; return NULL;}size_t Process::getPageSize(void){ init_sysinfo(); return (size_t) lpSysInfo->dwPageSize;}int Process::spawn(const char *exename, const char **args, bool wait){ int mode = P_NOWAIT; if(wait) mode = P_WAIT; return (int)::spawnvp(mode, (char *)exename, (char **)args);}int Process::join(int pid){ int status, result; if(pid == -1) return pid; result = (int)cwait(&status, pid, WAIT_CHILD); if(status & 0x0) return -1; return result;}bool Process::cancel(int pid, int sig){ HANDLE hPid = OpenProcess(PROCESS_TERMINATE, FALSE, pid); bool rtn = true; if(!hPid) return false; switch(sig) { case SIGABRT: case SIGTERM: if(!TerminateProcess(hPid, -1)) rtn = false; case 0: break; default: rtn = false; } CloseHandle(hPid); return rtn;}void Process::setPriority(int pri){ DWORD pc = NORMAL_PRIORITY_CLASS; DWORD pid = GetCurrentProcessId(); HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, TRUE, pid);#ifdef BELOW_NORMAL_PRIORITY_CLASS if(pri == -1) pc = BELOW_NORMAL_PRIORITY_CLASS; else if(pri == 1) pc = ABOVE_NORMAL_PRIORITY_CLASS; else#endif if(pri == 2) pc = HIGH_PRIORITY_CLASS; else if(pri > 2) pc = REALTIME_PRIORITY_CLASS; else if(pri < -1) pc = IDLE_PRIORITY_CLASS; SetPriorityClass(hProcess, pc); CloseHandle(hProcess);}void Process::setScheduler(const char *cp){ if(!stricmp(cp, "fifo")) setPriority(3); else if(!stricmp(cp, "rr")) setPriority(2); else if(!stricmp(cp, "idle")) setPriority(-2); else setPriority(0);}void Process::setRealtime(int pri){ setPriority(3);}bool Process::isScheduler(void){ return false;}#else#ifndef WEXITSTATUS#define WEXITSTATUS(status) ((unsigned)(status) >> 8)#endif#ifndef WIFEXITED#define WIFEXITED(status) (((status) & 255) == 0)#endif#ifndef WTERMSIG#define WTERMSIG(status) (((unsigned)(status)) & 0x7F)#endif#ifndef WIFSIGNALLED#define WIFSIGNALLED(status) (((status) & 255) != 0)#endif#ifndef WCOREDUMP#define WCOREDUMP(status) (((status) & 0x80) != 0)#endifstatic void lookup(void){ struct passwd *pw = NULL;#ifdef HAVE_GETPWUID_R struct passwd pwd; char buffer[1024]; ::getpwuid_r(geteuid(), &pwd, buffer, 1024, &pw);#else pw = ::getpwuid(geteuid());#endif if(_pHome) delString(_pHome); if(_pUser) delString(_pUser); _pUser = _pHome = NULL; if(pw != NULL && pw->pw_dir != NULL) _pHome = newString(pw->pw_dir); if(pw != NULL && pw->pw_name != NULL) _pUser = newString(pw->pw_name); endpwent();}const char *Process::getUser(void){ if(!_pUser) lookup(); return (const char *)_pUser;}const char *Process::getConfigDir(void){#ifdef ETC_CONFDIR return ETC_CONFDIR;#else return ETC_PREFIX;#endif} const char *Process::getHomeDir(void){ if(!_pHome) lookup(); return (const char *)_pHome;}#ifdef HAVE_GETPAGESIZEsize_t Process::getPageSize(void){ return (size_t)getpagesize();}#elsesize_t Process::getPageSize(void){ return 1024;}#endifbool Process::setUser(const char *id, bool grp){ struct passwd *pw = NULL;#ifdef HAVE_GETPWNAM_R struct passwd pwd; char buffer[1024]; ::getpwnam_r(id, &pwd, buffer, 1024, &pw);#else pw = ::getpwnam(id);#endif if(!pw) return false; if(grp) if(setgid(pw->pw_gid)) return false; if(setuid(pw->pw_uid)) return false; lookup(); return true;}bool Process::setGroup(const char *id){ struct group *group = NULL;#ifdef HAVE_GETGRNAM_R struct group grp; char buffer[2048]; ::getgrnam_r(id, &grp, buffer, 1024, &group);#else group = ::getgrnam(id);#endif if(!group) { endgrent(); return false; }#ifdef HAVE_SETEGID setegid(group->gr_gid);#endif if(setgid(group->gr_gid)) { endgrent(); return false; } endgrent(); return true;}bool Process::cancel(int pid, int sig){ if(!sig) sig = SIGTERM; if(pid < 1) return false; if(::kill(pid, sig)) return false; return true;}int Process::join(int pid){ int status; if(pid < 1) return -1;#ifdef HAVE_WAITPID waitpid(pid, &status, 0);#else#ifdef HAVE_WAIT4 wait4(pid, &status, 0, NULL);#else int result; while((result = wait(&status)) != pid && result != -1) ;#endif#endif if(WIFEXITED(status)) return WEXITSTATUS(status); else if(WIFSIGNALLED(status)) return -WTERMSIG(status); else return -1;}int Process::spawn(const char *exename, const char **args, bool wait){ int pid; pid = vfork(); if(pid == -1) return -1; if(!pid) { execvp((char *)exename, (char **)args); _exit(-1); } if(!wait) return pid; return join(pid);}Process::Trap Process::setInterruptSignal(int signo, Trap func){ struct sigaction sig_act, old_act; memset(&sig_act, 0, sizeof(sig_act)); sig_act.sa_handler = func; sigemptyset(&sig_act.sa_mask); if(signo != SIGALRM) sigaddset(&sig_act.sa_mask, SIGALRM); sig_act.sa_flags = 0;#ifdef SA_INTERRUPT sig_act.sa_flags |= SA_INTERRUPT;#endif if(sigaction(signo, &sig_act, &old_act) < 0) return SIG_ERR; return old_act.sa_handler;}Process::Trap Process::setPosixSignal(int signo, Trap func){ struct sigaction sig_act, old_act; memset(&sig_act, 0, sizeof(sig_act)); sig_act.sa_handler = func; sigemptyset(&sig_act.sa_mask); sig_act.sa_flags = 0; if(signo == SIGALRM) {#ifdef SA_INTERRUPT sig_act.sa_flags |= SA_INTERRUPT;#endif } else { sigaddset(&sig_act.sa_mask, SIGALRM);#ifdef SA_RESTART sig_act.sa_flags |= SA_RESTART;#endif } if(sigaction(signo, &sig_act, &old_act) < 0) return SIG_ERR; return old_act.sa_handler;}void Process::detach(void){ attach("/dev/null");}void Process::attach(const char *dev){ int pid; int fd; if(getppid() == 1) return; ::close(0); ::close(1); ::close(2);#ifdef SIGTTOU setPosixSignal(SIGTTOU, SIG_IGN);#endif#ifdef SIGTTIN setPosixSignal(SIGTTIN, SIG_IGN);#endif#ifdef SIGTSTP setPosixSignal(SIGTSTP, SIG_IGN);#endif if((pid = fork()) < 0) THROW(pid); else if(pid > 0) exit(0);#if defined(SIGTSTP) && defined(TIOCNOTTY) if(setpgid(0, getpid()) == -1) THROW(-1); if((fd = open(_PATH_TTY, O_RDWR)) >= 0) { ioctl(fd, TIOCNOTTY, NULL); close(fd); }#else#ifdef HAVE_SETPGRP if(setpgrp() == -1) THROW(-1);#else if(setpgid(0, getpid()) == -1) THROW(-1);#endif setPosixSignal(SIGHUP, SIG_IGN); if((pid = fork()) < 0) THROW(-1); else if(pid > 0) exit(0);#endif if(dev && *dev) { ::open(dev, O_RDWR); ::open(dev, O_RDWR); ::open(dev, O_RDWR); }}void Process::setScheduler(const char *pol){#ifdef _POSIX_PRIORITY_SCHEDULING struct sched_param p; int policy; sched_getparam(0, &p); if(pol) {#if defined(SCHED_TS) policy = SCHED_TS;#elif defined(SCHED_OTHER) policy = SCHED_OTHER;#else policy = 0;#endif#ifdef SCHED_RR if(!stricmp(pol, "rr")) policy = SCHED_RR;#endif#if !defined(SCHED_RR) && defined(SCHED_FIFO) if(!stricmp(pol, "rr")) policy = SCHED_FIFO;#endif#ifdef SCHED_FIFO if(!stricmp(pol, "fifo")) policy = SCHED_FIFO;#endif#ifdef SCHED_TS if(!stricmp(pol, "ts")) policy = SCHED_TS;#endif #ifdef SCHED_OTHER if(!stricmp(pol, "other")) policy = SCHED_OTHER;#endif } else policy = sched_getscheduler(0); int min = sched_get_priority_min(policy); int max = sched_get_priority_max(policy); if(p.sched_priority < min) p.sched_priority = min; else if(p.sched_priority > max) p.sched_priority = max; sched_setscheduler(0, policy, &p);#endif}void Process::setPriority(int pri){#ifdef _POSIX_PRIORITY_SCHEDULING struct sched_param p; int policy = sched_getscheduler(0); int min = sched_get_priority_min(policy); int max = sched_get_priority_max(policy); sched_getparam(0, &p); if(pri < min) pri = min; if(pri > max) pri = max; p.sched_priority = pri; sched_setparam(0, &p);#else if(pri < -20) pri = -20; if(pri > 20) pri = 20; nice(-pri);#endif}bool Process::isScheduler(void){#ifdef _POSIX_PRIORITY_SCHEDULING return true;#else return false;#endif}void Process::setRealtime(int pri){ if(pri < 1) pri = 1; setScheduler("rr"); setPriority(pri);} #endif // not win32#ifdef _OSF_SOURCE#undef HAVE_SETENV#endifvoid Process::setEnv(const char *name, const char *value, bool overwrite){#ifdef HAVE_SETENV ::setenv(name, value, (int)overwrite);#else char strbuf[256]; snprintf(strbuf, sizeof(strbuf), "%s=%s", name, value); if(!overwrite) if(getenv(strbuf)) return; ::putenv(strdup(strbuf));#endif}const char *Process::getEnv(const char *name){ return ::getenv(name);}#if defined(HAVE_MLOCKALL) && defined(MCL_FUTURE)#include <sys/mman.h>bool Process::lock(bool future){ int rc; if(future) rc = mlockall(MCL_CURRENT | MCL_FUTURE); else rc = mlockall(MCL_CURRENT); if(rc) return false; return true;}void Process::unlock(void){ munlockall();}#elsebool Process::lock(bool future){ return false;}void Process::unlock(void){}#endif#ifdef CCXX_NAMESPACES}#endif/** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -