home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / condor40.zip / CONDOR / src / condor_starter / starter.c < prev    next >
C/C++ Source or Header  |  1989-09-18  |  19KB  |  835 lines

  1. /* 
  2. ** Copyright 1986, 1987, 1988, 1989 University of Wisconsin
  3. ** 
  4. ** Permission to use, copy, modify, and distribute this software and its
  5. ** documentation for any purpose and without fee is hereby granted,
  6. ** provided that the above copyright notice appear in all copies and that
  7. ** both that copyright notice and this permission notice appear in
  8. ** supporting documentation, and that the name of the University of
  9. ** Wisconsin not be used in advertising or publicity pertaining to
  10. ** distribution of the software without specific, written prior
  11. ** permission.  The University of Wisconsin makes no representations about
  12. ** the suitability of this software for any purpose.  It is provided "as
  13. ** is" without express or implied warranty.
  14. ** 
  15. ** THE UNIVERSITY OF WISCONSIN DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. ** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. ** FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN  BE LIABLE FOR
  18. ** ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. ** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  21. ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. ** 
  23. ** Authors:  Allan Bricker and Michael J. Litzkow,
  24. **              University of Wisconsin, Computer Sciences Dept.
  25. ** 
  26. */ 
  27.  
  28.  
  29. #include <stdio.h>
  30. #include <pwd.h>
  31. #include <signal.h>
  32. #include <sys/types.h>
  33. #include <sys/file.h>
  34. #include <sys/stat.h>
  35. #include <sys/wait.h>
  36. #include <sys/time.h>
  37. #include <sys/resource.h>
  38. #include <sys/param.h>
  39. #include <rpc/types.h>
  40. #include <rpc/xdr.h>
  41. #include <errno.h>
  42. #include <a.out.h>
  43.  
  44. #include "debug.h"
  45. #include "except.h"
  46. #include "proc.h"
  47. #include "trace.h"
  48. #include "xdr_lib.h"
  49. #include "condor_sys.h"
  50. #include "fileno.h"
  51. #include "expr.h"
  52. #ifdef DAYAO
  53. #include "ctrace.h"
  54. #endif DAYAO
  55.  
  56.  
  57. static char *_FileName_ = __FILE__;        /* Used by EXCEPT (see except.h)     */
  58. char    *param();
  59.  
  60. #define MINUTE 60
  61. #define HOUR (MINUTE * 60)
  62.  
  63. extern int    errno;
  64.  
  65. int        CondorGid, CondorUid;
  66. char    *Execute;
  67. int        MinCkptInterval;
  68. int        MaxCkptInterval;
  69. int        CkptInterval;
  70.  
  71. int        ChildPid;
  72. char    Shortname[ MAXPATHLEN ];
  73. char    CkptTmpName[ MAXPATHLEN ];
  74.  
  75. char    *CoreName = "core";
  76.  
  77. char    *CkptName = NULL;
  78. char    *Stdin = NULL;
  79. char    *Stdout = NULL;
  80. char    *Stderr = NULL;
  81. char    *RootDir = NULL;
  82. char    *CmdName = NULL;
  83. char    *Args = NULL;
  84. char    *JobArgs[ MAXPATHLEN / 2 ];
  85. int        Cluster, Proc;
  86. int        Suspended;
  87. int        CkptCreated;
  88. int        JobExited;
  89. int        Aborted;
  90. struct rusage AccumRusage;
  91.  
  92. int        vacate_order(), checkpoint_order(), suspend_order(), resume_order();
  93. int        Cleanup(), die(), abort();
  94.  
  95. main( argc, argv )
  96. int        argc;
  97. char    *argv[];
  98. {
  99.     int        i, nfds;
  100.     union wait status;
  101.     struct rusage rusage;
  102.     XDR        *xdrs, *RSC_Init();
  103.  
  104.     (void) SetSyscalls( SYS_LOCAL | SYS_UNRECORDED );
  105.  
  106.  
  107.     setlinebuf( stderr );
  108.  
  109.     DebugFlags |= D_ALWAYS | D_NOHEADER;
  110.     /*
  111.     DebugFlags |= D_CKPT;
  112.     */
  113.     dprintf( D_ALWAYS, "********** STARTER starting up ***********\n" );
  114.  
  115.     config( argv[0], (CONTEXT *)0 );
  116.  
  117.     /*
  118.     dprintf_config( "STARTER", CLIENT_LOG );
  119.     */
  120.  
  121.     get_condor_uid();
  122.  
  123.     _EXCEPT_Cleanup = Cleanup;
  124.  
  125.     if( argc != 2 )
  126.         usage();
  127.  
  128.     init_params();
  129.  
  130.     set_sigs();
  131.     (void)sigsetmask( 0 );
  132.  
  133.     if( chdir(Execute) ) {
  134.         EXCEPT( "chdir(%s)", Execute );
  135.     }
  136.  
  137.     if( chroot(Execute) < 0 ) {
  138.         EXCEPT( "chroot(%s)", Execute );
  139.     }
  140.  
  141.     if( setregid(CondorGid,CondorGid) < 0 ) {
  142.         EXCEPT( "setregid(%d, %d)", CondorGid, CondorGid );
  143.     }
  144.  
  145.     if( setreuid(CondorUid,CondorUid) < 0 ) {
  146.         EXCEPT( "sereuid(%d, %d)", CondorUid, CondorUid );
  147.     }
  148.  
  149.  
  150.     (void)dup2( 1, RSC_SOCK );
  151.  
  152.     (void)dup2( 2, CLIENT_LOG );
  153.     stderr->_file = CLIENT_LOG;
  154.     
  155.  
  156.     xdrs = RSC_Init( RSC_SOCK, CLIENT_LOG );
  157.     xdrrec_skiprecord(xdrs);
  158.  
  159.     GetFileNames( xdrs );
  160.  
  161.     nfds = getdtablesize();
  162.     for( i=0; i<nfds; i++ ) {
  163.         if( i==RSC_SOCK || i==CLIENT_LOG ) continue;
  164.         (void)close( i );
  165.     }
  166.  
  167.     GetJobFile( xdrs );
  168.  
  169.     if( magic_check(Shortname) < 0 ) {
  170.         bzero( (char *)&AccumRusage, sizeof(AccumRusage) );
  171.         status.w_termsig = 0;        /* no sig, but a coredump -- can only */
  172.         status.w_coredump = 1;        /* be if we set it on purpose */
  173.         status.w_retcode = ENOEXEC;    /* now say why we didn't run the job */
  174.         (void)REMOTE_syscall( PSEUDO_reallyexit, &status, &AccumRusage);
  175.         Cleanup();
  176.         exit( 0 );
  177.     }
  178.  
  179.     CkptInterval = MinCkptInterval;
  180.     /*  I don't think this is needed -- mike
  181.     if( Suspended ) {
  182.         sigpause( ~(sigmask(SIGCONT) | sigmask(SIGTSTP)) );
  183.     }
  184.     */
  185.     for(;;) {
  186.         (void)sigsetmask( ~0 );
  187.         if( (ChildPid = vfork()) < 0 ) {
  188.             EXCEPT( "vfork" );
  189.         }
  190.  
  191.         if( ChildPid ) {        /* The parent */
  192.             (void)sigsetmask( 0 );
  193.  
  194.             (void)alarm( (unsigned)CkptInterval );
  195.             dprintf( D_ALWAYS, "Set alarm for %d seconds\n", CkptInterval );
  196.  
  197.             WaitForChild(&status, &rusage);
  198.             (void)alarm( (unsigned) 0 );
  199.  
  200.             update_rusage( &AccumRusage, &rusage );
  201.  
  202.             dprintf( D_FULLDEBUG, "Accumulated Rusage\n" );
  203.             dprintf( D_FULLDEBUG, "ru_utime = %d.%06d\n",
  204.                     AccumRusage.ru_utime.tv_sec, AccumRusage.ru_utime.tv_usec );
  205.             dprintf( D_FULLDEBUG, "ru_stime = %d.%06d\n",
  206.                     AccumRusage.ru_stime.tv_sec, AccumRusage.ru_stime.tv_usec );
  207.  
  208.             if( Aborted && CkptCreated ) {
  209.                 SendCkptFile( Shortname, CkptName );
  210.                 status.w_termsig = SIGQUIT;
  211.             }
  212.  
  213.             if( JobExited || Aborted ) {
  214.                 dprintf(D_FULLDEBUG, "Cleaning up now.\n");
  215.                 Cleanup();
  216.                 dprintf( D_FULLDEBUG, "Accumulated Rusage After Cleanup\n" );
  217.                 dprintf( D_FULLDEBUG, "ru_utime = %d.%06d\n",
  218.                     AccumRusage.ru_utime.tv_sec, AccumRusage.ru_utime.tv_usec );
  219.                 dprintf( D_FULLDEBUG, "ru_stime = %d.%06d\n",
  220.                     AccumRusage.ru_stime.tv_sec, AccumRusage.ru_stime.tv_usec );
  221.                 dprintf( D_ALWAYS, "********** STARTER exiting ***********\n" );
  222.                 /*
  223.                 ** Make sure that the log socket is read before the
  224.                 ** syscall socket.
  225.                 sleep( 1 );
  226.                 */
  227.                 (void)REMOTE_syscall( PSEUDO_reallyexit, &status, &AccumRusage);
  228.                 exit( 0 );
  229.             }
  230.             CkptInterval = MIN( 2 * CkptInterval, MaxCkptInterval );
  231.  
  232.         } else {                /* The child */
  233.             dprintf( D_ALWAYS, "Starter: Doing execv( %s, 0x%x )\n",
  234.                 Shortname, JobArgs );
  235.             (void)execv( Shortname, JobArgs );
  236.             EXCEPT( "execv(%s)", Shortname );
  237.         }
  238.     }
  239. }
  240.  
  241.  
  242. WaitForChild(statp, rusagep)
  243. union wait *statp;
  244. struct rusage *rusagep;
  245. {
  246.     int pid;
  247.     int    scm;
  248.  
  249.     dprintf( D_FULLDEBUG, "Starter: waiting for \"%s\" (pid %d) to die\n",
  250.                                                 Shortname, ChildPid );
  251.  
  252.     while( (pid=wait3(statp, 0, rusagep)) < 0 ) {
  253.         if( errno != EINTR ) {
  254.             EXCEPT( "wait3" );
  255.         }
  256.     }
  257.  
  258.     if( pid != ChildPid ) {
  259.         EXCEPT("wait3 returned pid %d (not %d)\n", pid, ChildPid );
  260.     }
  261.     ChildPid = 0;
  262.  
  263.     dprintf(D_ALWAYS,
  264.         "Pid %d exited, termsig = %d, coredump = %d, retcode = %d\n",
  265.             pid, statp->w_termsig,
  266.             statp->w_coredump, statp->w_retcode
  267.     );
  268.  
  269.     dprintf( D_FULLDEBUG, "ru_utime = %d.%06d\n",
  270.             rusagep->ru_utime.tv_sec, rusagep->ru_utime.tv_usec );
  271.     dprintf( D_FULLDEBUG, "ru_stime = %d.%06d\n",
  272.             rusagep->ru_stime.tv_sec, rusagep->ru_stime.tv_usec );
  273.  
  274.     switch( statp->w_termsig ) {
  275.         case 0:            /* Normal Exit */
  276.             JobExited = TRUE;
  277.             break;
  278.         case SIGKILL:     /* Kicked Off */
  279.             bzero( (char *)rusagep, sizeof(struct rusage) );
  280.             JobExited = TRUE;
  281.             Aborted = TRUE;
  282. #ifdef DAYAO
  283.             scm = SetSyscalls( SYS_REMOTE | SYS_UNRECORDED );
  284.             if( ProcessLogging(CATCH_SIGKILL,0) < 0 ) {
  285.                 EXCEPT( "ProcessLogging(CATCH_SIGKILL,0)" );
  286.             }
  287.             (void)SetSyscalls( scm );
  288. #endif DAYAO
  289.             break;
  290.         case SIGQUIT:    /* Periodic checkpoint */
  291.             /*  I don't think this is needed -- mike
  292.             if( Suspended ) {
  293.                 sigpause( ~(sigmask(SIGCONT) | sigmask(SIGTSTP)) );
  294.             }
  295.             */
  296.             if( !Aborted ) {
  297.                 do_ckpt();
  298.             }
  299.             break;
  300.         default:        /* Abnormal Exit */
  301.             if( statp->w_coredump ) {
  302.                 SendBackCore();
  303.             }
  304.             JobExited = TRUE;
  305.             break;
  306.     }
  307. }
  308.  
  309.  
  310.  
  311. do_ckpt()
  312. {
  313. #if defined(vax) || defined(i386) || defined(mc68020) || defined(sparc)
  314.     /*
  315.     **    Checkpointing is only possible on the defined systems.
  316.     **    If this isn't one of them, we'll just restart the job from the
  317.     **    initial checkpoint and hopefully it will be able to complete.
  318.     */
  319.  
  320.     (void)sprintf(CkptTmpName, "%s.tmp", Shortname);
  321.     dprintf(D_ALWAYS, "Starter: About to _updateckpt(%s, %s, %s)\n",
  322.             CkptTmpName, Shortname, CoreName );
  323.  
  324.     _updateckpt( CkptTmpName, Shortname, CoreName );
  325.  
  326.     (void)unlink( Shortname );
  327.     (void)unlink( CoreName );
  328.     (void)rename( CkptTmpName, Shortname );
  329.     CkptCreated = 1;
  330. #endif defined(vax) || defined(i386) || defined(mc68020) || defined(sparc)
  331. }
  332.  
  333. SendBackCore()
  334. {
  335.     char    core_name[ MAXPATHLEN ];
  336.  
  337.     (void)sprintf( core_name, "core.%d.%d", Cluster, Proc );
  338.     dprintf(D_CKPT, "Sending back core file to \"%s\".\n", core_name);
  339.     SendBackFile( "core", core_name );
  340. }
  341.  
  342.  
  343. Cleanup()
  344. {
  345.     (void) SetSyscalls( SYS_LOCAL | SYS_UNRECORDED );
  346.  
  347.     (void)sigsetmask( ~0 );
  348.  
  349.     if( ChildPid ) {
  350.         (void)kill(ChildPid, SIGKILL);
  351.     }
  352.  
  353.     (void)unlink( CoreName );
  354.  
  355.     if( Shortname[0] != 0 ) {
  356.         (void)unlink( Shortname );
  357.     }
  358.     if( CkptTmpName && CkptTmpName[0] ) {
  359.         (void)unlink( CkptTmpName );
  360.     }
  361. }
  362.  
  363. usage()
  364. {
  365.     dprintf( D_ALWAYS, "Usage: starter init_machine\n" );
  366.     exit( 1 );
  367. }
  368.  
  369. /*
  370. ** Get the Condor job off the machine asap.
  371. */
  372. vacate_order()
  373. {
  374.     union wait    fake_status;
  375.  
  376.     dprintf(D_ALWAYS, "Got SIGINT, killed by the startd.\n" );
  377.     Aborted = TRUE;
  378.  
  379.     if( ChildPid ) {
  380.         (void)kill(ChildPid, SIGKILL);
  381.         dprintf( D_ALWAYS, "Sent SIGKILL to user job\n" );
  382.     } else {
  383.  
  384.         if( CkptCreated ) {
  385.             SendCkptFile( Shortname, CkptName );
  386.             fake_status.w_termsig = SIGQUIT;    /* Kicked off with ckpt */
  387.         } else {
  388.             fake_status.w_termsig = SIGKILL;    /* Kicked off without ckpt */
  389.         }
  390.         (void)REMOTE_syscall( PSEUDO_reallyexit, &fake_status, &AccumRusage);
  391.         dprintf( D_ALWAYS, "No user job running\n" );
  392.         dprintf(D_FULLDEBUG, "Cleaning up now.\n");
  393.         Cleanup();
  394.         exit( 1 );
  395.     }
  396. }
  397.  
  398. die()
  399. {
  400.     Cleanup();
  401.     exit( 1 );
  402. }
  403.  
  404. /*
  405. ** Send the Condor job an order to do a checkpoint.
  406. */
  407. checkpoint_order()
  408. {
  409.     if( ChildPid == 0 ) {
  410.         dprintf(D_FULLDEBUG, "Cleaning up now.\n");
  411.         Cleanup();
  412.     } else {
  413.         (void)kill(ChildPid, SIGCONT);
  414.         (void)kill(ChildPid, SIGTSTP);
  415.         dprintf( D_ALWAYS, "Got SIGALRM, sent SIGCONT & SIGTSTP to user job\n");
  416.     }
  417. }
  418.  
  419. int        SavedAlarm;
  420.  
  421. /*
  422. ** Suspend the Condor job.
  423. */
  424. suspend_order()
  425. {
  426.     if( ChildPid != 0 ) {
  427.         (void)kill(ChildPid, SIGSTOP);
  428.         dprintf( D_ALWAYS, "Got SIGUSR1, sent SIGSTOP to user job\n" );
  429.     }
  430.     SavedAlarm = alarm( 0 );
  431.     dprintf( D_ALWAYS, "Stopped alarm clock, %d seconds remaining\n",
  432.                                                         SavedAlarm );
  433.     Suspended = TRUE;
  434.  
  435.         /* Try this for now, see how it works out */
  436.     sigpause( sigmask(SIGUSR1) );
  437. }
  438.  
  439. /*
  440. ** Resume running the Condor job.
  441. */
  442. resume_order()
  443. {
  444.     if( ChildPid != 0 ) {
  445.         (void)kill(ChildPid, SIGCONT);
  446.         dprintf( D_ALWAYS, "Got SIGCONT, sent SIGCONT to user job\n" );
  447.     }
  448.     (void)alarm( (unsigned)SavedAlarm );
  449.     dprintf( D_ALWAYS, "Reset alarm clock, %d seconds remaining\n",
  450.                                                         SavedAlarm );
  451.     Suspended = FALSE;
  452. }
  453.  
  454. GetFileNames( xdrs )
  455. XDR *xdrs;
  456. {
  457.     PROC    proc;
  458.  
  459.     bzero( (char *)&proc, sizeof(PROC) );
  460.  
  461.     xdrs->x_op = XDR_DECODE;
  462.     ASSERT(xdr_proc(xdrs, &proc));
  463.     ASSERT( xdr_string(xdrs,&CkptName,MAXPATHLEN) );
  464.  
  465.  
  466.     Cluster = proc.id.cluster;
  467.     Proc    = proc.id.proc;
  468.     CmdName = proc.cmd;
  469.     Stdin   = proc.in;
  470.     Stdout  = proc.out;
  471.     Stderr  = proc.err;
  472.     Args    = proc.args;
  473.     RootDir = proc.rootdir;
  474.  
  475.     dprintf( D_PROC, "Cluster = %d\n", Cluster );
  476.     dprintf( D_PROC, "Proc = %d\n", Proc );
  477.     dprintf( D_PROC, "CkptName = \"%s\"\n", CkptName );
  478.     dprintf( D_PROC, "Stdin = \"%s\"\n", Stdin );
  479.     dprintf( D_PROC, "Stdout = \"%s\"\n", Stdout );
  480.     dprintf( D_PROC, "Stderr = \"%s\"\n", Stderr );
  481.     dprintf( D_PROC, "RootDir = \"%s\"\n", RootDir );
  482.     dprintf( D_PROC, "CmdName = \"%s\"\n", CmdName );
  483.     dprintf( D_PROC, "Args = \"%s\"\n", Args );
  484.  
  485.     (void)sprintf( Shortname, "condor_exec%06d.%d", Cluster, Proc );
  486. }
  487.  
  488. GetJobFile( xdrs )
  489. XDR        *xdrs;
  490. {
  491.     int        len;
  492.     int        got, written;
  493.     int        fd;
  494.     char    buf[XDR_BLOCKSIZ];
  495.     int        argc;
  496.  
  497.         /* Copy in the file */
  498.     if( (fd=open(Shortname,O_WRONLY | O_CREAT,0775)) < 0 ) {
  499.         EXCEPT( "open of \"%s\"", Shortname );
  500.     }
  501.     dprintf( D_FULLDEBUG, "Opened file \"%s\"\n", Shortname );
  502.         
  503.     ASSERT( xdr_int(xdrs,&len) );
  504.  
  505.     while( len ) {
  506.         got = len < XDR_BLOCKSIZ ? len : XDR_BLOCKSIZ;
  507.  
  508.         errno = 0;
  509.         ASSERT( xdr_opaque(xdrs, buf, got) );
  510.  
  511.         if( (written=write(fd,buf,got)) != got ) {
  512.             EXCEPT( "write" );
  513.         }
  514.  
  515.         len -= written;
  516.     }
  517.  
  518.     (void)close( fd );
  519.     dprintf( D_FULLDEBUG, "Closed \"%s\"\n", Shortname );
  520.  
  521.     mkargv( &argc, &JobArgs[1], Args );
  522.     JobArgs[0] = Shortname;
  523. }
  524.  
  525. get_condor_uid()
  526. {
  527.     struct passwd    *pwd;
  528.  
  529.     if( (pwd=getpwnam("condor")) == NULL ) {
  530.         EXCEPT( "Can't find passwd entry for condor" );
  531.     }
  532.  
  533.     CondorUid = pwd->pw_uid;
  534.     CondorGid = pwd->pw_gid;
  535. }
  536.  
  537.  
  538.  
  539. SendCkptFile( local_name, remote_name )
  540. char    *local_name;
  541. char    *remote_name;
  542. {
  543.     char    tmp_name[ MAXPATHLEN ];
  544.  
  545.     (void)sprintf( tmp_name, "%s.tmp", remote_name );
  546.     dprintf( D_FULLDEBUG, "SendCkptFile() called\n" );
  547.     dprintf( D_FULLDEBUG, "local_name = \"%s\"\n", local_name );
  548.     dprintf( D_FULLDEBUG, "remote_name = \"%s\"\n", remote_name );
  549.     dprintf( D_FULLDEBUG, "tmp_name = \"%s\"\n", tmp_name );
  550.  
  551.     SendBackFile( local_name, tmp_name );
  552.  
  553.     (void) SetSyscalls( SYS_REMOTE | SYS_UNRECORDED );
  554.     if( rename(tmp_name,remote_name) < 0 ) {
  555.         EXCEPT( "remote_rename(%s,%s)", tmp_name, remote_name );
  556.     }
  557.     (void) SetSyscalls( SYS_LOCAL | SYS_UNRECORDED );
  558.     dprintf( D_ALWAYS, "Returned latest checkpoint\n" );
  559. }
  560.  
  561. /*
  562. ** Send a file to the initiating machine using the remote system call
  563. ** mechanism.
  564. */
  565. SendBackFile( local_name, remote_name )
  566. char    *local_name;
  567. char    *remote_name;
  568. {
  569.     int        ifd, ofd;
  570.     int        got, sent;
  571.     char     buf[ 16 * 1024 ];
  572.     int        scm, len;
  573.  
  574.     scm = SetSyscalls( SYS_LOCAL | SYS_UNRECORDED );
  575.     if( (ifd=open(local_name,O_RDONLY)) < 0 ) {
  576.         EXCEPT( "open(%s,O_RDONLY)", local_name );
  577.     }
  578.  
  579.     (void) SetSyscalls( SYS_REMOTE | SYS_UNRECORDED );
  580. #ifdef DAYAO
  581.     if( ProcessLogging(START_LOGGING,0) < 0 ) {
  582.         EXCEPT( "ProcessLogging(START_LOGGING,0) (pseudo call)" );
  583.     }
  584. #endif DAYAO
  585.     if( (ofd=open(remote_name,O_WRONLY|O_CREAT,0664)) < 0 ) {
  586.         EXCEPT( "remote_open(%s,O_WRONLY|O_CREAT,0664)", remote_name );
  587.     }
  588.  
  589. #ifdef DAYAO
  590.     for(len=0;;len+=sent) {
  591. #else
  592.     for(;;) {
  593. #endif DAYAO
  594.         (void) SetSyscalls( SYS_LOCAL | SYS_UNRECORDED );
  595.         if( (got = read( ifd, buf, sizeof(buf) )) < 0 ) {
  596.             EXCEPT( "read(%d,0x%x,%d)", ifd, buf, sizeof(buf) );
  597.         }
  598.  
  599.         if( got == 0 ) {
  600.             break;
  601.         }
  602.     
  603.         (void) SetSyscalls( SYS_REMOTE | SYS_UNRECORDED );
  604.         if( (sent = write( ofd, buf, got )) != got ) {
  605.             EXCEPT( "remote_write(%d,0x%x,%d) returns %d", ofd, buf, got, sent);
  606.         }
  607.     }
  608.  
  609.     (void) SetSyscalls( SYS_REMOTE | SYS_UNRECORDED );
  610.     if( close(ofd) < 0 ) {
  611.         EXCEPT( "remote_close(%d)", ofd );
  612.     }
  613. #ifdef DAYAO
  614.     if( ProcessLogging(COMPLETE_LOGGING,len) < 0 ) {
  615.         EXCEPT( "ProcessLogging(COMPLETE_LOGGING,0) (pseudo call)" );
  616.     }
  617. #endif DAYAO
  618.  
  619.     (void) SetSyscalls( SYS_LOCAL | SYS_UNRECORDED );
  620.     if( close(ifd) < 0 ) {
  621.         EXCEPT( "close(%d)", ifd );
  622.     }
  623.  
  624.     (void) SetSyscalls( scm );
  625. }
  626.  
  627. update_rusage( ru1, ru2 )
  628. register struct rusage *ru1, *ru2;
  629. {
  630.     ru1->ru_utime.tv_usec += ru2->ru_utime.tv_usec;
  631.     if( ru1->ru_utime.tv_usec >= 1000000 ) {
  632.         ru1->ru_utime.tv_usec -= 1000000;
  633.         ru1->ru_utime.tv_sec += 1;
  634.     }
  635.     ru1->ru_utime.tv_sec += ru2->ru_utime.tv_sec;
  636.  
  637.     ru1->ru_stime.tv_usec += ru2->ru_stime.tv_usec;
  638.     if( ru1->ru_stime.tv_usec >= 1000000 ) {
  639.         ru1->ru_stime.tv_usec -= 1000000;
  640.         ru1->ru_stime.tv_sec += 1;
  641.     }
  642.     ru1->ru_stime.tv_sec += ru2->ru_stime.tv_sec;
  643.  
  644.     if( ru2->ru_maxrss > ru1->ru_maxrss ) {
  645.         ru1->ru_maxrss = ru2->ru_maxrss;
  646.     }
  647.     if( ru2->ru_ixrss > ru1->ru_ixrss ) {
  648.         ru1->ru_ixrss = ru2->ru_ixrss;
  649.     }
  650.     if( ru2->ru_idrss > ru1->ru_idrss ) {
  651.         ru1->ru_idrss = ru2->ru_idrss;
  652.     }
  653.     if( ru2->ru_isrss > ru1->ru_isrss ) {
  654.         ru1->ru_isrss = ru2->ru_isrss;
  655.     }
  656.     ru1->ru_minflt += ru2->ru_minflt;
  657.     ru1->ru_majflt += ru2->ru_majflt;
  658.     ru1->ru_nswap += ru2->ru_nswap;
  659.     ru1->ru_inblock += ru2->ru_inblock;
  660.     ru1->ru_oublock += ru2->ru_oublock;
  661.     ru1->ru_msgsnd += ru2->ru_msgsnd;
  662.     ru1->ru_msgrcv += ru2->ru_msgrcv;
  663.     ru1->ru_nsignals += ru2->ru_nsignals;
  664.     ru1->ru_nvcsw += ru2->ru_nvcsw;
  665.     ru1->ru_nivcsw += ru2->ru_nivcsw;
  666. }
  667.  
  668. init_params()
  669. {
  670.     char    *tmp;
  671.  
  672.     if( (Execute=param("EXECUTE")) == NULL ) {
  673.         EXCEPT( "Execute directory not specified in config file" );
  674.     }
  675.  
  676.     if( (tmp=param("MIN_CKPT_INTERVAL")) == NULL ) {
  677.         MinCkptInterval = 15 * MINUTE;
  678.     } else {
  679.         MinCkptInterval = atoi( tmp );
  680.     }
  681.  
  682.     if( (tmp=param("MAX_CKPT_INTERVAL")) == NULL ) {
  683.         MaxCkptInterval = 2 * HOUR;
  684.     } else {
  685.         MaxCkptInterval = atoi( tmp );
  686.     }
  687.  
  688.     if( MaxCkptInterval > 2 * HOUR ) {
  689.         MaxCkptInterval = 2 * HOUR;
  690.     }
  691.  
  692.     if( MaxCkptInterval < 15 * MINUTE ) {
  693.         MaxCkptInterval = 15 * MINUTE;
  694.     }
  695.  
  696.     if( MinCkptInterval < 15 * MINUTE ) {
  697.         MinCkptInterval = 15 * MINUTE;
  698.     }
  699.  
  700.     if( MinCkptInterval > MaxCkptInterval ) {
  701.         MinCkptInterval = MaxCkptInterval;
  702.     }
  703.  
  704. }
  705.  
  706. #define SETSIG(s,f) \
  707.     if( signal(s, f) < 0 ) { \
  708.         EXCEPT( "Can't set signal %d to 0x%x", s, f ); \
  709.     }
  710.  
  711. set_sigs()
  712. {
  713.     int        i;
  714.  
  715.     for( i=1; i<NSIG; i++ ) {
  716.         switch( i ) {
  717.             case SIGKILL:
  718.             case SIGSTOP:
  719.                 break;
  720.             case SIGINT:
  721.                 SETSIG( i, die );
  722.                 break;
  723.             case SIGQUIT:
  724.                 SETSIG( i, abort );
  725.                 break;
  726.             case SIGTSTP:
  727.                 SETSIG( i, vacate_order );
  728.                 break;
  729.             case SIGUSR1:
  730.                 SETSIG( i, suspend_order );
  731.                 break;
  732.             case SIGCONT:
  733.                 SETSIG( i, resume_order );
  734.                 break;
  735.             case SIGALRM:
  736.                 SETSIG( i, checkpoint_order );
  737.                 break;
  738.             case SIGCHLD:
  739.                 SETSIG( i, SIG_IGN );
  740.                 break;
  741.             default:
  742.                 SETSIG( i, die );
  743.         }
  744.     }
  745. }
  746.  
  747. abort()
  748. {
  749.     char    wd[1024];
  750.  
  751.     getwd( wd );
  752.     Cleanup();
  753.     SETSIG( SIGILL, SIG_DFL );
  754.     dprintf( D_ALWAYS, "Got abort signal, CWD = \"%s\"\n", wd );
  755.     kill( getpid(), SIGILL );
  756.     sigpause( 0 );
  757. }
  758.  
  759. /*
  760. ** Check the header of the file we are about to exec.  Make sure everything
  761. ** is reasonable.
  762. */
  763. #ifdef MIPS
  764. magic_check( name )
  765. char *name;
  766. {
  767.     return( 0 );
  768. }
  769. #else MIPS
  770. magic_check( name )
  771. char    *name;
  772. {
  773.     int        fd;
  774.     struct exec    exec;
  775.     int        scm;
  776.  
  777.     scm = SetSyscalls( SYS_LOCAL | SYS_UNRECORDED );
  778.  
  779.     if( (fd=open(name,O_RDONLY,0)) < 0 ) {
  780.         EXCEPT( "open(%s,O_RDONLY,0)", name );
  781.     }
  782.  
  783.     if( read(fd,(char *)&exec,sizeof(struct exec)) != sizeof(struct exec) ) {
  784.         EXCEPT( "read(%d,0x%x,%d)", fd, &exec, sizeof(struct exec) );
  785.     }
  786.     (void)close( fd );
  787.  
  788.     (void)SetSyscalls( scm );
  789.  
  790. #ifdef vax
  791.     if( exec.a_magic != ZMAGIC ) {
  792.         dprintf( D_ALWAYS, "\"%s\": BAD MAGIC NUMBER\n", name );
  793.         return -1;
  794.     }
  795. #endif
  796.  
  797. #ifdef sequent
  798.     if( exec.a_magic != ZMAGIC ) {
  799.         dprintf( D_ALWAYS, "\"%s\": BAD MAGIC NUMBER\n", name );
  800.         return -1;
  801.     }
  802. #endif sequent
  803.  
  804. #ifdef sparc
  805.     if( exec.a_magic != ZMAGIC ) {
  806.         dprintf( D_ALWAYS, "\"%s\": BAD MAGIC NUMBER\n", name );
  807.         return -1;
  808.     }
  809.     if( exec.a_machtype != M_SPARC ) {
  810.         dprintf( D_ALWAYS, "\"%s\": NOT COMPILED FOR SPARC ARCHITECTURE\n",
  811.                                                             name );
  812.         return -1;
  813.     }
  814.     if( exec.a_dynamic ) {
  815.         dprintf( D_ALWAYS, "\"%s\": LINKED FOR DYNAMIC LOADING\n", name );
  816.         return -1;
  817.     }
  818. #endif
  819.         
  820. #ifdef mc68020
  821.     if( exec.a_magic != ZMAGIC ) {
  822.         dprintf( D_ALWAYS, "\"%s\": BAD MAGIC NUMBER\n", name );
  823.         return -1;
  824.     }
  825.     if( exec.a_machtype != M_68020 ) {
  826.         dprintf( D_ALWAYS, "\"%s\": NOT COMPILED FOR MC68020 ARCHITECTURE\n",
  827.                                                                 name );
  828.         return -1;
  829.     }
  830. #endif
  831.  
  832.     return 0;
  833. }
  834. #endif MIPS
  835.