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

📄 kprocess.cpp

📁 一种效率高
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent);}//////////////////////////////// private member functions ////////////////////////////////void KProcess::processHasExited(int state){  runs = FALSE;  status = state;  commClose(); // cleanup communication sockets  // also emit a signal if the process was run Blocking  if (DontCare != run_mode)    emit processExited(this);}int KProcess::childOutput(int fdno){  char buffer[1024];  int len;  len = ::read(fdno, buffer, 1024);  if ( 0 < len) {	emit receivedStdout(this, buffer, len);  }  return len;}int KProcess::childError(int fdno){  char buffer[1024];  int len;  len = ::read(fdno, buffer, 1024);  if ( 0 < len)	emit receivedStderr(this, buffer, len);  return len;}int KProcess::setupCommunication(Communication comm){  int ok;  communication = comm;  ok = 1;  if (comm & Stdin)	ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0;  if (comm & Stdout)	ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0;  if (comm & Stderr)	ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0;  return ok;}int KProcess::commSetupDoneP(){  int ok = 1;  if (communication != NoCommunication) {	if (communication & Stdin)	  close(in[0]);	if (communication & Stdout)	  close(out[1]);	if (communication & Stderr)	  close(err[1]);	// Don't create socket notifiers and set the sockets non-blocking if	// blocking is requested.	if (run_mode == Block) return ok;	if (communication & Stdin) {	  ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK));	  innot =  new QSocketNotifier(in[1], QSocketNotifier::Write, this);	  CHECK_PTR(innot);	  innot->setEnabled(FALSE); // will be enabled when data has to be sent	  QObject::connect(innot, SIGNAL(activated(int)),					   this, SLOT(slotSendData(int)));	}	if (communication & Stdout) {	  ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK));	  outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this);	  CHECK_PTR(outnot);	  QObject::connect(outnot, SIGNAL(activated(int)),					   this, SLOT(slotChildOutput(int)));	}	if (communication & Stderr) {	  ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK));	  errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this );	  CHECK_PTR(errnot);	  QObject::connect(errnot, SIGNAL(activated(int)),					   this, SLOT(slotChildError(int)));	}  }  return ok;}int KProcess::commSetupDoneC(){  int ok = 1;  struct linger so;  if (communication != NoCommunication) {	if (communication & Stdin)	  close(in[1]);	if (communication & Stdout)	  close(out[0]);	if (communication & Stderr)	  close(err[0]);	if (communication & Stdin)	  ok &= dup2(in[0],  STDIN_FILENO) != -1;	if (communication & Stdout) {	  ok &= dup2(out[1], STDOUT_FILENO) != -1;	  ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so));	}	if (communication & Stderr) {	  ok &= dup2(err[1], STDERR_FILENO) != -1;	  ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so));	}  }  return ok;}void KProcess::commClose(){  if (NoCommunication != communication) {        bool b_in = (communication & Stdin);        bool b_out = (communication & Stdout);        bool b_err = (communication & Stderr);	if (b_in)		delete innot;	if (b_out || b_err) {	  // If both channels are being read we need to make sure that one socket buffer	  // doesn't fill up whilst we are waiting for data on the other (causing a deadlock).	  // Hence we need to use select.	  // Once one or other of the channels has reached EOF (or given an error) go back	  // to the usual mechanism.	  int fds_ready = 1;	  fd_set rfds;          int max_fd = 0;          if (b_out) {            if (out[0] > max_fd)              max_fd = out[0];            delete outnot;          }          if (b_err) {            if (err[0] > max_fd)              max_fd = err[0];            delete errnot;          }           	  while (b_out || b_err) {	    FD_ZERO(&rfds);            if (b_out) 	      FD_SET(out[0], &rfds);            if (b_err) 	      FD_SET(err[0], &rfds);	    fds_ready = select(max_fd+1, &rfds, 0, 0, 0);	    if (fds_ready <= 0) break;	    if (b_out && FD_ISSET(out[0], &rfds)) {	      int ret = childOutput(out[0]);	      if ((ret == -1 && errno != EAGAIN) || ret == 0) 		b_out = false;	    }                               	    if (b_err && FD_ISSET(err[0], &rfds)) {	      int ret = childError(err[0]);	      if ((ret == -1 && errno != EAGAIN) || ret == 0) 		b_err = false;	    }	  }	}	if (communication & Stdin)	    close(in[1]);	if (communication & Stdout)	    close(out[0]);	if (communication & Stderr)	    close(err[0]);		communication = NoCommunication;  }}///////////////////////////// CC: Class KShellProcess///////////////////////////KShellProcess::KShellProcess(const char *shellname):  KProcess(){  if (0 != shellname)    shell = kstrdup(shellname);  else    shell = 0;}KShellProcess::~KShellProcess() {  if(shell)    free(shell);}bool KShellProcess::start(RunMode runmode, Communication comm){  uint i;  uint n = arguments.count();  char *arglist[4];  QString cmd;  if (runs || (0 == n)) {	return FALSE;  // cannot start a process that is already running	// or if no executable has been assigned  }  run_mode = runmode;  status = 0;  if (0 == shell)    shell = searchShell();  if (0 == shell) {    debug("Could not find a valid shell\n");    return FALSE;  }  // CC: Changed the way the parameter was built up  // CC: Arglist for KShellProcess is now always:  // CC: <shell> -c <command>  arglist[0] = shell;  arglist[1] = "-c";  for (i=0; i < n; i++) {    cmd += arguments.at(i);    cmd += " "; // CC: to separate the arguments  }//   // execution in background//   cmd.stripWhiteSpace();//   if (cmd[cmd.length()-1] != '&')//       cmd += '&';  arglist[2] = cmd.data();  arglist[3] = 0;  if (!setupCommunication(comm))    debug("Could not setup Communication!");  runs = TRUE;  pid = fork();  if (0 == pid) {	// The child process	if(!commSetupDoneC())	  debug("Could not finish comm setup in child!");	// Matthias	if (run_mode == DontCare)          setpgid(0,0);        // restore default SIGPIPE handler (Harri)        struct sigaction act;        sigemptyset(&(act.sa_mask));        sigaddset(&(act.sa_mask), SIGPIPE);        act.sa_handler = SIG_DFL;        act.sa_flags = 0;        sigaction(SIGPIPE, &act, 0L);	execvp(arglist[0], arglist);	exit(-1);  } else if (-1 == pid) {	// forking failed	runs = FALSE;	return FALSE;  } else {	// the parent continues here	if (!commSetupDoneP())  // finish communication socket setup for the parent	  debug("Could not finish comm setup in parent!");	// Discard any data for stdin that might still be there	input_data = 0;	if (run_mode == Block) {	  commClose();	  // Its possible that the child's exit was caught by the SIGCHLD handler	  // which will have set status for us.	  if (waitpid(pid, &status, 0) != -1) this->status = status;	  runs = FALSE;	  emit processExited(this);	}  }  return TRUE;}char *KShellProcess::searchShell(){  char *hlp = 0;  char *copy = 0;  // CC: now get the name of the shell we have to use  hlp = getenv("SHELL");  if (isExecutable(hlp)) {    copy = kstrdup(hlp);    CHECK_PTR(copy);  }  if (0 == copy) {    // CC: hmm, invalid $SHELL in environment -- maybe there are whitespaces to be stripped?    QString stmp = QString(shell);    QString shell_stripped = stmp.stripWhiteSpace();    if (isExecutable(shell_stripped.data())) {      copy = kstrdup(shell_stripped.data());      CHECK_PTR(copy);    }  }  return copy;}bool KShellProcess::isExecutable(const char *fname){  struct stat fileinfo;  if ((0 == fname) || (strlen(fname) == 0)) return FALSE;  // CC: filename is invalid  // CC: we've got a valid filename, now let's see whether we can execute that file  if (-1 == stat(fname, &fileinfo)) return FALSE;  // CC: return false if the file does not exist  // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets  if ( (S_ISDIR(fileinfo.st_mode))  ||       (S_ISCHR(fileinfo.st_mode))  ||       (S_ISBLK(fileinfo.st_mode))  ||#ifdef S_ISSOCK       // CC: SYSVR4 systems don't have that macro       (S_ISSOCK(fileinfo.st_mode)) ||#endif       (S_ISFIFO(fileinfo.st_mode)) ||       (S_ISDIR(fileinfo.st_mode)) ) {    return FALSE;  }  // CC: now check for permission to execute the file  if (access(fname, X_OK) != 0) return FALSE;  // CC: we've passed all the tests...  return TRUE;}#include "kprocess.moc"

⌨️ 快捷键说明

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