16 #include "support/lstrings.h"
17 #include "support/lyxlib.h"
22 Systemcalls::Systemcalls() {
23 pid = 0; // No child yet
26 Systemcalls::Systemcalls(Starttype how, string const & what, Callbackfct cback)
28 startscript(how, what, cback);
31 Systemcalls::~Systemcalls() {
33 // If the child is alive, we have to brutally kill it
35 lyx::kill(getpid(), SIGKILL);
40 // Start a childprocess
42 // if child runs in background, add information to global controller.
44 int Systemcalls::startscript() {
49 retval = ::system(command.c_str());
54 if (pid>0) { // Fork succesful. Wait for child
63 // Now integrate into Controller
64 SystemcallsSingletoncontroller::Startcontroller starter;
65 SystemcallsSingletoncontroller * contr = starter.getController();
66 // Add this to controller
67 contr->addCall(*this);
75 void Systemcalls::kill(int /*tolerance*/) {
77 lyxerr << "LyX: Can't kill non-existing process." << endl;
80 int ret = lyx::kill(getpid(), SIGHUP);
81 bool wait_for_death = true;
84 // The process is already dead!
85 wait_for_death = false;
87 // Something is rotten - maybe we lost permissions?
91 // Here, we should add the PID to a list of
92 // waiting processes to kill if they are not
93 // dead within tolerance seconds
95 // CHECK Implement this using the timer of
96 // the singleton systemcontroller (Asger)
102 // Wait for child process to finish. Returns returncode from child.
103 void Systemcalls::waitForChild() {
104 // We'll pretend that the child returns 1 on all errorconditions.
109 pid_t waitrpid = waitpid(pid, &status, WUNTRACED);
110 if (waitrpid == -1) {
111 lyxerr << "LyX: Error waiting for child:" << strerror(errno) << endl;
113 } else if (WIFEXITED(status)) {
114 // Child exited normally. Update return value.
115 retval = WEXITSTATUS(status);
117 } else if (WIFSIGNALED(status)) {
118 lyxerr << "LyX: Child didn't catch signal "
120 << "and died. Too bad." << endl;
122 } else if (WIFSTOPPED(status)) {
123 lyxerr << "LyX: Child (pid: " << pid
124 << ") stopped on signal "
126 << ". Waiting for child to finish." << endl;
128 lyxerr << "LyX: Something rotten happened while "
129 "waiting for child " << pid << endl;
136 // generate child in background
138 pid_t Systemcalls::fork()
140 pid_t cpid= ::fork();
141 if (cpid == 0) { // child
142 // TODO: Consider doing all of this before the fork, otherwise me
143 // might have troubles with multi-threaded access. (Baruch 20010228)
144 string childcommand(command); // copy
145 string rest = split(command, childcommand, ' ');
146 const int MAX_ARGV = 255;
148 char *argv[MAX_ARGV];
152 childcommand = frontStrip(childcommand);
154 syscmd = new char[childcommand.length() + 1];
155 childcommand.copy(syscmd, childcommand.length());
156 syscmd[childcommand.length()] = '\0';
158 if (!childcommand.empty()) {
159 char * tmp = new char[childcommand.length() + 1];
160 childcommand.copy(tmp, childcommand.length());
161 tmp[childcommand.length()] = '\0';
166 more = !rest.empty();
168 rest = split(rest, childcommand, ' ');
171 // replace by command. Expand using PATH-environment-var.
172 execvp(syscmd, argv);
173 // If something goes wrong, we end up here:
174 lyxerr << "LyX: execvp failed: " << strerror(errno) << endl;
175 } else if (cpid < 0) { // error
176 lyxerr << "LyX: Could not fork: " << strerror(errno) << endl;
186 int Systemcalls::startscript(Starttype how, string const & what,
192 pid = static_cast<pid_t>(0); // yet no child
195 if (how == SystemDontWait) {
199 // OS/2 cmd.exe has another use for '&'
200 // This is not NLS safe, but it's OK, I think.
201 string sh = OnlyFilename(GetEnvPath("EMXSHELL"));
203 // COMSPEC is set, unless user unsets
204 sh = OnlyFilename(GetEnvPath("COMSPEC"));
209 if (contains(sh, "cmd.exe")
210 || contains(sh, "4os2.exe"))
211 command = "start /min/n " + command;
217 return startscript();
223 // Mini-Test-environment for script-classes
230 void back(string cmd, int retval)
232 ::printf("Done: %s gave %d\n", cmd.c_str(), retval);
237 int main(int, char **)
240 SystemcallsSingletoncontroller::Startcontroller starter;
241 SystemcallsSingletoncontroller *contr= starter.GetController();
243 Systemcalls one(Systemcalls::System, "ls -ltag", back);
244 Systemcalls two(Systemcalls::Wait, "ls -ltag", back);
246 Systemcalls three(Systemcalls::DontWait , "ls -ltag", back);
247 // Simulation of timer
248 while (SimulateTimer)