X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Fsyscall.C;fp=src%2Fsupport%2Fsyscall.C;h=9a9e1ecc547b8b1dbef0b9e8aebf8933d8d26b48;hb=59e18b17aec378d71ca7d8ef3e566be40c35aaf1;hp=597dd362de113360e86bab3000b4741b86646ad4;hpb=d208f37600974ad73b20bde4d83ad862513148cd;p=lyx.git diff --git a/src/support/syscall.C b/src/support/syscall.C index 597dd362de..9a9e1ecc54 100644 --- a/src/support/syscall.C +++ b/src/support/syscall.C @@ -1,214 +1,42 @@ +/** + * \file syscall.C + * Copyright 2002 the LyX Team + * Read the file COPYING + * + * \author Asger Alstrup + * + * Interface cleaned up by + * \author Angus Leeming + * + * Class Systemcalls uses "system" to launch the child process. + * The user can choose to wait or not wait for the process to complete, but no + * callback is invoked upon completion of the child. + * + * The child process is not killed when the Systemcall instance goes out of + * scope. + */ + #include #ifdef __GNUG__ #pragma implementation #endif -#include -#include -#include -#include -#include -#include -#include "debug.h" #include "syscall.h" -#include "syscontr.h" -#include "support/lstrings.h" -#include "support/lyxlib.h" -#include "support/filetools.h" -#include "support/os.h" - -using std::endl; - -#ifndef CXX_GLOBAL_CSTD -using std::strerror; -#endif - - -Systemcalls::Systemcalls() { - pid = 0; // No child yet -} - -Systemcalls::Systemcalls(Starttype how, string const & what, Callbackfct cback) -{ - startscript(how, what, cback); -} - -Systemcalls::~Systemcalls() { -#if 0 - // If the child is alive, we have to brutally kill it - if (getpid() != 0) { - lyx::kill(getpid(), SIGKILL); - } -#endif -} - -// Start a childprocess -// -// if child runs in background, add information to global controller. - -int Systemcalls::startscript() { - retval = 0; - switch (start) { - case System: - case SystemDontWait: - retval = ::system(command.c_str()); - callback(); - break; - case Wait: - pid = fork(); - if (pid>0) { // Fork succesful. Wait for child - waitForChild(); - callback(); - } else - retval = 1; - break; - case DontWait: - pid = fork(); - if (pid>0) { - // Now integrate into Controller - SystemcallsSingletoncontroller::Startcontroller starter; - SystemcallsSingletoncontroller * contr = starter.getController(); - // Add this to controller - contr->addCall(*this); - } else - retval = 1; - break; - } - return retval; -} - -void Systemcalls::kill(int /*tolerance*/) { - if (getpid() == 0) { - lyxerr << "LyX: Can't kill non-existing process." << endl; - return; - } - int ret = lyx::kill(getpid(), SIGHUP); - bool wait_for_death = true; - if (ret != 0) { - if (errno == ESRCH) { - // The process is already dead! - wait_for_death = false; - } else { - // Something is rotten - maybe we lost permissions? - } - } - if (wait_for_death) { - // Here, we should add the PID to a list of - // waiting processes to kill if they are not - // dead within tolerance seconds - - // CHECK Implement this using the timer of - // the singleton systemcontroller (Asger) - - } -} - - -// Wait for child process to finish. Returns returncode from child. -void Systemcalls::waitForChild() { - // We'll pretend that the child returns 1 on all errorconditions. - retval = 1; - int status; - bool wait = true; - while (wait) { - pid_t waitrpid = waitpid(pid, &status, WUNTRACED); - if (waitrpid == -1) { - lyxerr << "LyX: Error waiting for child:" - << strerror(errno) << endl; - wait = false; - } else if (WIFEXITED(status)) { - // Child exited normally. Update return value. - retval = WEXITSTATUS(status); - wait = false; - } else if (WIFSIGNALED(status)) { - lyxerr << "LyX: Child didn't catch signal " - << WTERMSIG(status) - << "and died. Too bad." << endl; - wait = false; - } else if (WIFSTOPPED(status)) { - lyxerr << "LyX: Child (pid: " << pid - << ") stopped on signal " - << WSTOPSIG(status) - << ". Waiting for child to finish." << endl; - } else { - lyxerr << "LyX: Something rotten happened while " - "waiting for child " << pid << endl; - wait = false; - } - } -} +#include "os.h" - -// generate child in background - -pid_t Systemcalls::fork() +Systemcalls::Systemcalls(Starttype how, string const & what) { - #ifndef __EMX__ - pid_t cpid= ::fork(); - if (cpid == 0) { // child - #endif - // TODO: Consider doing all of this before the fork, otherwise me - // might have troubles with multi-threaded access. (Baruch 20010228) - string childcommand(command); // copy - string rest = split(command, childcommand, ' '); - const int MAX_ARGV = 255; - char *syscmd = 0; - char *argv[MAX_ARGV]; - int index = 0; - bool more = true; - while (more) { - childcommand = frontStrip(childcommand); - if (syscmd == 0) { - syscmd = new char[childcommand.length() + 1]; - childcommand.copy(syscmd, childcommand.length()); - syscmd[childcommand.length()] = '\0'; - } - if (!childcommand.empty()) { - char * tmp = new char[childcommand.length() + 1]; - childcommand.copy(tmp, childcommand.length()); - tmp[childcommand.length()] = '\0'; - argv[index++] = tmp; - } - - // reinit - more = !rest.empty(); - if (more) - rest = split(rest, childcommand, ' '); - } - argv[index] = 0; - // replace by command. Expand using PATH-environment-var. -#ifndef __EMX__ - execvp(syscmd, argv); - // If something goes wrong, we end up here: - lyxerr << "LyX: execvp(" << syscmd << ") failed: " - << strerror(errno) << endl; - } else if (cpid < 0) { // error -#else - pid_t cpid = spawnvp(P_SESSION|P_DEFAULT|P_MINIMIZE|P_BACKGROUND, syscmd, argv); - if (cpid < 0) { // error -#endif - lyxerr << "LyX: Could not fork: " - << strerror(errno) << endl; - } else { // parent - return cpid; - } - return 0; + startscript(how, what); } // Reuse of instance - -int Systemcalls::startscript(Starttype how, string const & what, - Callbackfct cback) +int Systemcalls::startscript(Starttype how, string const & what) { - start = how; - command = what; - cbk = cback; - pid = static_cast(0); // yet no child - retval = 0; + string command = what; - if (how == SystemDontWait) { + if (how == DontWait) { if (os::shell() == os::UNIX) { command += " &"; } else { @@ -216,41 +44,5 @@ int Systemcalls::startscript(Starttype how, string const & what, } } - return startscript(); + return ::system(command.c_str()); } - - - -// -// Mini-Test-environment for script-classes -// -#ifdef TEST_MAIN -#include - - -int SimulateTimer; -void back(string cmd, int retval) -{ - ::printf("Done: %s gave %d\n", cmd.c_str(), retval); - SimulateTimer = 0; -} - - -int main(int, char **) -{ - - SystemcallsSingletoncontroller::Startcontroller starter; - SystemcallsSingletoncontroller *contr= starter.GetController(); - - Systemcalls one(Systemcalls::System, "ls -ltag", back); - Systemcalls two(Systemcalls::Wait, "ls -ltag", back); - SimulateTimer = 1; - Systemcalls three(Systemcalls::DontWait , "ls -ltag", back); - // Simulation of timer - while (SimulateTimer) - { - sleep(1); - contr->Timer(); - } -} -#endif