17 #include "support/lstrings.h"
19 Systemcalls::Systemcalls() {
20 pid = (pid_t) 0; // No child yet
23 Systemcalls::Systemcalls(Starttype how, string const & what, Callbackfct cback)
33 Systemcalls::~Systemcalls() {
35 // If the child is alive, we have to brutally kill it
37 ::kill(getpid(), SIGKILL);
42 // Start a childprocess
44 // if child runs in background, add information to global controller.
46 int Systemcalls::startscript() {
50 retval = system(command.c_str());
55 if (pid>0) { // Fork succesful. Wait for child
64 // Now integrate into Controller
65 SystemcallsSingletoncontroller::Startcontroller starter;
66 SystemcallsSingletoncontroller * contr = starter.getController();
67 // Add this to controller
68 contr->addCall(*this);
76 void Systemcalls::kill(int tolerance) {
78 lyxerr << "LyX: Can't kill non-existing process." << endl;
81 int ret = ::kill(getpid(), SIGHUP);
82 bool wait_for_death = true;
85 // The process is already dead!
86 wait_for_death = false;
88 // Something is rotten - maybe we lost permissions?
92 // Here, we should add the PID to a list of
93 // waiting processes to kill if they are not
94 // dead without tolerance seconds
95 #warning Implement this using the timer of the singleton systemcontroller (Asger)
100 // Wait for child process to finish. Returns returncode from child.
101 void Systemcalls::waitForChild() {
102 // We'll pretend that the child returns 1 on all errorconditions.
107 pid_t waitrpid = waitpid(pid, &status, WUNTRACED);
108 if (waitrpid == -1) {
109 lyxerr << "LyX: Error waiting for child:" << strerror(errno) << endl;
111 } else if (WIFEXITED(status)) {
112 // Child exited normally. Update return value.
113 retval = WEXITSTATUS(status);
115 } else if (WIFSIGNALED(status)) {
116 lyxerr << "LyX: Child didn't catch signal "
118 << "and died. Too bad." << endl;
120 } else if (WIFSTOPPED(status)) {
121 lyxerr << "LyX: Child (pid: " << pid
122 << ") stopped on signal "
124 << ". Waiting for child to finish." << endl;
126 lyxerr << "LyX: Something rotten happened while "
127 "waiting for child " << pid << endl;
134 // generate child in background
136 pid_t Systemcalls::fork()
138 pid_t cpid= ::fork();
139 if (cpid == 0) { // child
140 string childcommand(command); // copy
141 string rest = split(command, childcommand, ' ');
142 const int MAX_ARGV = 255;
144 char *argv[MAX_ARGV];
149 syscmd = new char[childcommand.length() + 1];
150 childcommand.copy(syscmd, childcommand.length());
151 syscmd[childcommand.length()] = '\0';
153 char * tmp = new char[childcommand.length() + 1];
154 childcommand.copy(tmp, childcommand.length());
155 tmp[childcommand.length()] = '\0';
158 more = !rest.empty();
160 rest = split(rest, childcommand, ' ');
163 // replace by command. Expand using PATH-environment-var.
164 execvp(syscmd, argv);
165 // If something goes wrong, we end up here:
166 lyxerr << "LyX: execvp failed: " << strerror(errno) << endl;
167 } else if (cpid < 0) { // error
168 lyxerr << "LyX: Could not fork: " << strerror(errno) << endl;
178 int Systemcalls::startscript(Starttype how, string const & what,
184 pid = (pid_t) 0; // yet no child
186 return startscript();
192 // Mini-Test-environment for script-classes
199 void back(string cmd, int retval)
201 printf("Done: %s gave %d\n", cmd.c_str(), retval);
206 int main(int, char**)
209 SystemcallsSingletoncontroller::Startcontroller starter;
210 SystemcallsSingletoncontroller *contr=starter.GetController();
212 Systemcalls one(Systemcalls::System, "ls -ltag", back);
213 Systemcalls two(Systemcalls::Wait, "ls -ltag", back);
215 Systemcalls three(Systemcalls::DontWait , "ls -ltag", back);
216 // Simulation of timer
217 while (SimulateTimer)