1999-09-27 18:44:28 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#ifdef __GNUG__
|
|
|
|
#pragma implementation
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
1999-10-02 16:21:10 +00:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstdio>
|
1999-09-27 18:44:28 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include "syscall.h"
|
|
|
|
#include "syscontr.h"
|
1999-10-02 16:21:10 +00:00
|
|
|
#include "support/lstrings.h"
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Class, which controlls a system-call
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
// constructor
|
|
|
|
Systemcalls::Systemcalls()
|
|
|
|
{
|
|
|
|
pid = (pid_t) 0; // yet no child
|
|
|
|
}
|
|
|
|
|
|
|
|
// constructor
|
|
|
|
//
|
|
|
|
// starts child
|
1999-10-02 16:21:10 +00:00
|
|
|
Systemcalls::Systemcalls(Starttype how, string what, Callbackfct cback)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
|
|
|
start = how;
|
|
|
|
command = what;
|
|
|
|
cbk = cback;
|
|
|
|
pid = (pid_t) 0; // no child yet
|
|
|
|
retval = 0;
|
|
|
|
Startscript();
|
|
|
|
}
|
|
|
|
|
|
|
|
// destructor
|
|
|
|
// not yet implemented (?)
|
|
|
|
Systemcalls::~Systemcalls()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start a childprocess
|
|
|
|
//
|
|
|
|
// if child runs in background, add information to global controller.
|
|
|
|
|
|
|
|
int Systemcalls::Startscript()
|
|
|
|
{
|
|
|
|
retval = 0;
|
|
|
|
switch (start) {
|
|
|
|
case System:
|
|
|
|
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 contr
|
|
|
|
contr->AddCall(*this);
|
|
|
|
} else
|
|
|
|
retval = 1;
|
|
|
|
break;
|
|
|
|
//default: // error();
|
|
|
|
//break;
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
perror("LyX: Error waiting for child");
|
|
|
|
wait = false;
|
|
|
|
} else if (WIFEXITED(status)) {
|
|
|
|
// Child exited normally. Update return value.
|
|
|
|
retval = WEXITSTATUS(status);
|
|
|
|
wait = false;
|
|
|
|
} else if (WIFSIGNALED(status)) {
|
|
|
|
fprintf(stderr,"LyX: Child didn't catch signal %d "
|
|
|
|
"and died. Too bad.\n", WTERMSIG(status));
|
|
|
|
wait = false;
|
|
|
|
} else if (WIFSTOPPED(status)) {
|
|
|
|
fprintf(stderr,"LyX: Child (pid: %ld) stopped on "
|
|
|
|
"signal %d. Waiting for child to finish.\n",
|
|
|
|
(long) pid, WSTOPSIG(status));
|
|
|
|
} else {
|
|
|
|
fprintf(stderr,"LyX: Something rotten happened while "
|
|
|
|
"waiting for child %ld\n", (long) pid);
|
|
|
|
wait = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// generate child in background
|
|
|
|
|
|
|
|
pid_t Systemcalls::Fork()
|
|
|
|
{
|
|
|
|
pid_t cpid=fork();
|
|
|
|
if (cpid == 0) { // child
|
1999-10-02 16:21:10 +00:00
|
|
|
string childcommand(command); // copy
|
|
|
|
string rest = split(command, childcommand, ' ');
|
1999-09-27 18:44:28 +00:00
|
|
|
const int MAX_ARGV = 255;
|
1999-10-02 16:21:10 +00:00
|
|
|
char *syscmd = 0;
|
1999-09-27 18:44:28 +00:00
|
|
|
char *argv[MAX_ARGV];
|
|
|
|
int index = 0;
|
|
|
|
bool Abbruch;
|
|
|
|
do {
|
1999-10-02 16:21:10 +00:00
|
|
|
if (syscmd == 0) {
|
|
|
|
syscmd = new char[childcommand.length() + 1];
|
|
|
|
childcommand.copy(syscmd, childcommand.length());
|
|
|
|
syscmd[childcommand.length()] = '\0';
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
1999-10-02 16:21:10 +00:00
|
|
|
char * tmp = new char[childcommand.length() + 1];
|
|
|
|
childcommand.copy(tmp, childcommand.length());
|
|
|
|
tmp[childcommand.length()] = '\0';
|
|
|
|
argv[index++] = tmp;
|
1999-09-27 18:44:28 +00:00
|
|
|
// reinit
|
|
|
|
Abbruch = !rest.empty();
|
|
|
|
if (Abbruch)
|
1999-10-02 16:21:10 +00:00
|
|
|
rest = split(rest, childcommand, ' ');
|
1999-09-27 18:44:28 +00:00
|
|
|
} while (Abbruch);
|
1999-10-02 16:21:10 +00:00
|
|
|
argv[index] = 0;
|
1999-09-27 18:44:28 +00:00
|
|
|
// replace by command. Expand using PATH-environment-var.
|
|
|
|
execvp(syscmd, argv);
|
|
|
|
// If something goes wrong, we end up here:
|
|
|
|
perror("LyX: execvp failed");
|
|
|
|
} else if (cpid < 0) { // error
|
|
|
|
perror("LyX: Could not fork");
|
|
|
|
} else { // parent
|
|
|
|
return cpid;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Reuse of instance
|
|
|
|
|
1999-10-02 16:21:10 +00:00
|
|
|
int Systemcalls::Startscript(Starttype how, string what, Callbackfct cback)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
|
|
|
start = how;
|
|
|
|
command = what;
|
|
|
|
cbk = cback;
|
|
|
|
pid = (pid_t) 0; // yet no child
|
|
|
|
retval = 0;
|
|
|
|
return Startscript();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Mini-Test-environment for script-classes
|
|
|
|
//
|
|
|
|
#ifdef TEST_MAIN
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
|
|
int SimulateTimer;
|
1999-10-02 16:21:10 +00:00
|
|
|
void back(string cmd, int retval)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
|
|
|
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
|