16 #include "support/lstrings.h"
17 #include "support/lyxlib.h"
18 #include "support/filetools.h"
19 #include "support/os.h"
23 #ifndef CXX_GLOBAL_CSTD
28 Systemcalls::Systemcalls() {
29 pid = 0; // No child yet
32 Systemcalls::Systemcalls(Starttype how, string const & what, Callbackfct cback)
34 startscript(how, what, cback);
37 Systemcalls::~Systemcalls() {
39 // If the child is alive, we have to brutally kill it
41 lyx::kill(getpid(), SIGKILL);
46 // Start a childprocess
48 // if child runs in background, add information to global controller.
50 int Systemcalls::startscript() {
55 retval = ::system(command.c_str());
60 if (pid>0) { // Fork succesful. Wait for child
69 // Now integrate into Controller
70 SystemcallsSingletoncontroller::Startcontroller starter;
71 SystemcallsSingletoncontroller * contr = starter.getController();
72 // Add this to controller
73 contr->addCall(*this);
81 void Systemcalls::kill(int /*tolerance*/) {
83 lyxerr << "LyX: Can't kill non-existing process." << endl;
86 int ret = lyx::kill(getpid(), SIGHUP);
87 bool wait_for_death = true;
90 // The process is already dead!
91 wait_for_death = false;
93 // Something is rotten - maybe we lost permissions?
97 // Here, we should add the PID to a list of
98 // waiting processes to kill if they are not
99 // dead within tolerance seconds
101 // CHECK Implement this using the timer of
102 // the singleton systemcontroller (Asger)
108 // Wait for child process to finish. Returns returncode from child.
109 void Systemcalls::waitForChild() {
110 // We'll pretend that the child returns 1 on all errorconditions.
115 pid_t waitrpid = waitpid(pid, &status, WUNTRACED);
116 if (waitrpid == -1) {
117 lyxerr << "LyX: Error waiting for child:"
118 << strerror(errno) << endl;
120 } else if (WIFEXITED(status)) {
121 // Child exited normally. Update return value.
122 retval = WEXITSTATUS(status);
124 } else if (WIFSIGNALED(status)) {
125 lyxerr << "LyX: Child didn't catch signal "
127 << "and died. Too bad." << endl;
129 } else if (WIFSTOPPED(status)) {
130 lyxerr << "LyX: Child (pid: " << pid
131 << ") stopped on signal "
133 << ". Waiting for child to finish." << endl;
135 lyxerr << "LyX: Something rotten happened while "
136 "waiting for child " << pid << endl;
143 // generate child in background
145 pid_t Systemcalls::fork()
148 pid_t cpid= ::fork();
149 if (cpid == 0) { // child
151 // TODO: Consider doing all of this before the fork, otherwise me
152 // might have troubles with multi-threaded access. (Baruch 20010228)
153 string childcommand(command); // copy
154 string rest = split(command, childcommand, ' ');
155 const int MAX_ARGV = 255;
157 char *argv[MAX_ARGV];
161 childcommand = frontStrip(childcommand);
163 syscmd = new char[childcommand.length() + 1];
164 childcommand.copy(syscmd, childcommand.length());
165 syscmd[childcommand.length()] = '\0';
167 if (!childcommand.empty()) {
168 char * tmp = new char[childcommand.length() + 1];
169 childcommand.copy(tmp, childcommand.length());
170 tmp[childcommand.length()] = '\0';
175 more = !rest.empty();
177 rest = split(rest, childcommand, ' ');
180 // replace by command. Expand using PATH-environment-var.
182 execvp(syscmd, argv);
183 // If something goes wrong, we end up here:
184 lyxerr << "LyX: execvp failed: "
185 << strerror(errno) << endl;
186 } else if (cpid < 0) { // error
188 pid_t cpid = spawnvp(P_SESSION|P_DEFAULT|P_MINIMIZE|P_BACKGROUND, syscmd, argv);
189 if (cpid < 0) { // error
191 lyxerr << "LyX: Could not fork: "
192 << strerror(errno) << endl;
202 int Systemcalls::startscript(Starttype how, string const & what,
208 pid = static_cast<pid_t>(0); // yet no child
211 if (how == SystemDontWait) {
212 if (os::shell() == os::UNIX) {
215 command = "start /min/n " + command;
219 return startscript();
225 // Mini-Test-environment for script-classes
232 void back(string cmd, int retval)
234 ::printf("Done: %s gave %d\n", cmd.c_str(), retval);
239 int main(int, char **)
242 SystemcallsSingletoncontroller::Startcontroller starter;
243 SystemcallsSingletoncontroller *contr= starter.GetController();
245 Systemcalls one(Systemcalls::System, "ls -ltag", back);
246 Systemcalls two(Systemcalls::Wait, "ls -ltag", back);
248 Systemcalls three(Systemcalls::DontWait , "ls -ltag", back);
249 // Simulation of timer
250 while (SimulateTimer)