home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / syscall.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  4KB  |  202 lines

  1. #include <config.h>
  2.  
  3. #ifdef __GNUG__
  4. #pragma implementation
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <sys/wait.h>
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <unistd.h>
  12. #include "syscall.h"
  13. #include "syscontr.h"
  14.  
  15. //----------------------------------------------------------------------
  16. // Class, which controlls a system-call
  17. //----------------------------------------------------------------------
  18.  
  19. // constructor
  20. Systemcalls::Systemcalls()
  21. {
  22.     pid = (pid_t) 0; // yet no child
  23. }
  24.  
  25. // constructor
  26. // 
  27. // starts child
  28. Systemcalls::Systemcalls(Starttype how, LString what, Callbackfct cback)
  29. {
  30.     start   = how;
  31.     command = what;
  32.     cbk     = cback;
  33.     pid     = (pid_t) 0; // no child yet
  34.     retval  = 0;
  35.     Startscript();
  36. }
  37.  
  38. // destructor
  39. // not yet implemented (?)
  40. Systemcalls::~Systemcalls()
  41. {
  42. }
  43.  
  44. // Start a childprocess
  45. // 
  46. // if child runs in background, add information to global controller.
  47.  
  48. int Systemcalls::Startscript()
  49. {
  50.     retval = 0;
  51.     switch (start) {
  52.     case System: 
  53.         retval = system(command.c_str());
  54.         Callback();
  55.         break;
  56.     case Wait:   
  57.         pid = Fork();
  58.         if (pid>0) { // Fork succesful. Wait for child
  59.             waitForChild();
  60.             Callback();
  61.         } else
  62.             retval = 1;
  63.         break;
  64.     case DontWait:
  65.         pid=Fork();
  66.         if (pid>0) {
  67.             // Now integrate into Controller
  68.             SystemcallsSingletoncontroller::Startcontroller starter;
  69.             SystemcallsSingletoncontroller *contr=
  70.                 starter.GetController();
  71.             // Add this to contr
  72.             contr->AddCall(*this);
  73.         } else
  74.             retval = 1;
  75.         break;
  76.         //default:  // error();
  77.         //break;
  78.     }
  79.     return retval;
  80. }
  81.  
  82.  
  83. // Wait for child process to finish. Returns returncode from child.
  84. void Systemcalls::waitForChild()
  85. {
  86.     // We'll pretend that the child returns 1 on all errorconditions.
  87.     retval = 1;
  88.     int status;
  89.     bool wait = true;
  90.     while (wait) {
  91.         pid_t waitrpid = waitpid(pid, &status, WUNTRACED);
  92.         if (waitrpid == -1) {
  93.             perror("LyX: Error waiting for child");
  94.             wait = false;
  95.         } else if (WIFEXITED(status)) {
  96.             // Child exited normally. Update return value.
  97.             retval = WEXITSTATUS(status);
  98.             wait = false;
  99.         } else if (WIFSIGNALED(status)) {
  100.             fprintf(stderr,"LyX: Child didn't catch signal %d "
  101.                 "and died. Too bad.\n", WTERMSIG(status));
  102.             wait = false;
  103.         } else if (WIFSTOPPED(status)) {
  104.             fprintf(stderr,"LyX: Child (pid: %ld) stopped on "
  105.                 "signal %d. Waiting for child to finish.\n", 
  106.                 (long) pid, WSTOPSIG(status));
  107.         } else {
  108.             fprintf(stderr,"LyX: Something rotten happened while "
  109.                 "waiting for child %ld\n", (long) pid);
  110.             wait = false;
  111.         }
  112.     }
  113. }
  114.  
  115.  
  116. // generate child in background
  117.  
  118. pid_t Systemcalls::Fork()
  119. {
  120.     pid_t cpid=fork();
  121.     if (cpid == 0) { // child
  122.         LString childcommand(command); // copy
  123.         LString rest = command.split(childcommand, ' ');
  124.         const MAX_ARGV=255;
  125.         char *syscmd = NULL; 
  126.         char *argv[MAX_ARGV];
  127.         int  index = 0;
  128.         bool Abbruch;
  129.         do {
  130.             if (syscmd == NULL) {
  131.                 syscmd = new char[childcommand.length()+1];
  132.                 childcommand.copy(syscmd, LString::npos);
  133.                 syscmd[childcommand.length()]=0;
  134.             }
  135.             argv[index++] = strdup(childcommand.c_str());
  136.             // reinit
  137.             Abbruch = !rest.empty();
  138.             if (Abbruch) 
  139.                 rest = rest.split(childcommand, ' ');
  140.         } while (Abbruch);
  141.         argv[index] = NULL;
  142.         // replace by command. Expand using PATH-environment-var.
  143.         execvp(syscmd, argv);
  144.         // If something goes wrong, we end up here:
  145.         perror("LyX: execvp failed");
  146.     } else if (cpid < 0) { // error
  147.         perror("LyX: Could not fork");
  148.     } else { // parent
  149.         return cpid;
  150.     }
  151.     return 0;
  152. }
  153.  
  154.  
  155. // Reuse of instance
  156.  
  157. int Systemcalls::Startscript(Starttype how, LString what, Callbackfct cback)
  158. {
  159.     start   = how;
  160.     command = what;
  161.     cbk     = cback;
  162.     pid     = (pid_t) 0; // yet no child
  163.     retval    = 0;
  164.         return Startscript();
  165. }
  166.  
  167.  
  168.  
  169. //
  170. // Mini-Test-environment for script-classes
  171. //
  172. #ifdef TEST_MAIN
  173. #include <stdio.h>
  174.  
  175.  
  176. int SimulateTimer;
  177. void back(LString cmd, int retval)
  178. {
  179.     printf("Done: %s gave %d\n", cmd.c_str(), retval);
  180.     SimulateTimer = 0;
  181. }
  182.  
  183.  
  184. int main(int, char**)
  185. {
  186.     
  187.     SystemcallsSingletoncontroller::Startcontroller starter; 
  188.     SystemcallsSingletoncontroller *contr=starter.GetController();
  189.     
  190.     Systemcalls one(Systemcalls::System, "ls -ltag", back);
  191.     Systemcalls two(Systemcalls::Wait, "ls -ltag", back);
  192.     SimulateTimer = 1;
  193.     Systemcalls three(Systemcalls::DontWait , "ls -ltag", back);
  194.     // Simulation of timer
  195.     while (SimulateTimer)
  196.         {
  197.             sleep(1);
  198.             contr->Timer();
  199.         }
  200. }
  201. #endif
  202.