]> git.lyx.org Git - lyx.git/blobdiff - src/support/syscall.C
We don't currently use fork anywhere (or if we do it's by mistake!), so
[lyx.git] / src / support / syscall.C
index 597dd362de113360e86bab3000b4741b86646ad4..9a9e1ecc547b8b1dbef0b9e8aebf8933d8d26b48 100644 (file)
+/**
+ *  \file syscall.C
+ *  Copyright 2002 the LyX Team
+ *  Read the file COPYING
+ *
+ * \author Asger Alstrup
+ *
+ * Interface cleaned up by
+ * \author Angus Leeming <a.leeming@ic.ac.uk>
+ *
+ * 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 <config.h>
 
 #ifdef __GNUG__
 #pragma implementation
 #endif
 
-#include <cerrno>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <csignal>
-#include <cstdlib>
-#include <unistd.h>
-#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<pid_t>(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 <stdio.h>
-
-
-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