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)
31 pid = static_cast<pid_t>(0);
36 Systemcalls::~Systemcalls() {
38 // If the child is alive, we have to brutally kill it
40 lyx::kill(getpid(), SIGKILL);
45 // Start a childprocess
47 // if child runs in background, add information to global controller.
49 int Systemcalls::startscript() {
53 retval = system(command.c_str());
58 if (pid>0) { // Fork succesful. Wait for child
67 // Now integrate into Controller
68 SystemcallsSingletoncontroller::Startcontroller starter;
69 SystemcallsSingletoncontroller * contr = starter.getController();
70 // Add this to controller
71 contr->addCall(*this);
79 void Systemcalls::kill(int /*tolerance*/) {
81 lyxerr << "LyX: Can't kill non-existing process." << endl;
84 int ret = lyx::kill(getpid(), SIGHUP);
85 bool wait_for_death = true;
88 // The process is already dead!
89 wait_for_death = false;
91 // Something is rotten - maybe we lost permissions?
95 // Here, we should add the PID to a list of
96 // waiting processes to kill if they are not
97 // dead without tolerance seconds
99 // CHECK Implement this using the timer of
100 // the singleton systemcontroller (Asger)
106 // Wait for child process to finish. Returns returncode from child.
107 void Systemcalls::waitForChild() {
108 // We'll pretend that the child returns 1 on all errorconditions.
113 pid_t waitrpid = waitpid(pid, &status, WUNTRACED);
114 if (waitrpid == -1) {
115 lyxerr << "LyX: Error waiting for child:" << strerror(errno) << endl;
117 } else if (WIFEXITED(status)) {
118 // Child exited normally. Update return value.
119 retval = WEXITSTATUS(status);
121 } else if (WIFSIGNALED(status)) {
122 lyxerr << "LyX: Child didn't catch signal "
124 << "and died. Too bad." << endl;
126 } else if (WIFSTOPPED(status)) {
127 lyxerr << "LyX: Child (pid: " << pid
128 << ") stopped on signal "
130 << ". Waiting for child to finish." << endl;
132 lyxerr << "LyX: Something rotten happened while "
133 "waiting for child " << pid << endl;
140 // generate child in background
142 pid_t Systemcalls::fork()
144 pid_t cpid= ::fork();
145 if (cpid == 0) { // child
146 string childcommand(command); // copy
147 string rest = split(command, childcommand, ' ');
148 const int MAX_ARGV = 255;
150 char *argv[MAX_ARGV];
154 childcommand = frontStrip(childcommand);
156 syscmd = new char[childcommand.length() + 1];
157 childcommand.copy(syscmd, childcommand.length());
158 syscmd[childcommand.length()] = '\0';
160 if (!childcommand.empty()) {
161 char * tmp = new char[childcommand.length() + 1];
162 childcommand.copy(tmp, childcommand.length());
163 tmp[childcommand.length()] = '\0';
168 more = !rest.empty();
170 rest = split(rest, childcommand, ' ');
173 // replace by command. Expand using PATH-environment-var.
174 execvp(syscmd, argv);
175 // If something goes wrong, we end up here:
176 lyxerr << "LyX: execvp failed: " << strerror(errno) << endl;
177 } else if (cpid < 0) { // error
178 lyxerr << "LyX: Could not fork: " << strerror(errno) << endl;
188 int Systemcalls::startscript(Starttype how, string const & what,
194 pid = static_cast<pid_t>(0); // yet no child
196 return startscript();
202 // Mini-Test-environment for script-classes
209 void back(string cmd, int retval)
211 printf("Done: %s gave %d\n", cmd.c_str(), retval);
216 int main(int, char **)
219 SystemcallsSingletoncontroller::Startcontroller starter;
220 SystemcallsSingletoncontroller *contr= starter.GetController();
222 Systemcalls one(Systemcalls::System, "ls -ltag", back);
223 Systemcalls two(Systemcalls::Wait, "ls -ltag", back);
225 Systemcalls three(Systemcalls::DontWait , "ls -ltag", back);
226 // Simulation of timer
227 while (SimulateTimer)