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_master / master.c < prev    next >
C/C++ Source or Header  |  1989-09-14  |  24KB  |  1,036 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 <signal.h>
  31. #include <errno.h>
  32. #include <pwd.h>
  33. #include <netdb.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <sys/wait.h>
  37. #include <sys/file.h>
  38. #include <sys/time.h>
  39. #include <sys/resource.h>
  40. #include "sched.h"
  41. #include "debug.h"
  42. #include "except.h"
  43. #include "expr.h"
  44.  
  45.  
  46. #define MAX_LINES 100
  47.  
  48. typedef struct {
  49.     long    data[MAX_LINES + 1];
  50.     int        first;
  51.     int        last;
  52.     int        size;
  53.     int        n_elem;
  54. } QUEUE;
  55.  
  56.  
  57. extern char    *SigNames[];
  58. char    *param(), *rindex(), *strdup(), *prog_name();
  59. int        sigchld_handler(), sigalrm_handler(), sigint_handler(),
  60.         sighup_handler(), sigquit_handler(), restart_master();
  61. long    delete_queue();
  62.  
  63. static char *_FileName_ = __FILE__;        /* Used by EXCEPT (see except.h)     */
  64.  
  65. #define MINUTE    60
  66. #define HOUR    60 * MINUTE
  67. #define MAX(a,b) ((a)>(b)?(a):(b))
  68.  
  69. char    *MyName;
  70.  
  71. time_t    GetTimeStamp();
  72.  
  73. int        KbdD_Restarts;
  74. int        KbdD_Pid;
  75. time_t    KbdD_TimeStamp;
  76.  
  77. int        SchedD_Restarts;
  78. int        SchedD_Pid;
  79. time_t    SchedD_TimeStamp;
  80.  
  81. int        StartD_Restarts;
  82. int        StartD_Pid;
  83. time_t    StartD_TimeStamp;
  84.  
  85. int        Collector_Restarts;
  86. int        Collector_Pid;
  87. time_t    Collector_TimeStamp;
  88.  
  89. int        Negotiator_Restarts;
  90. int        Negotiator_Pid;
  91. time_t    Negotiator_TimeStamp;
  92.  
  93. time_t    Master_TimeStamp;
  94. int        MasterLockFD;
  95.  
  96. char    *CollectorHost;
  97. char    *NegotiatorHost;
  98. int        RestartsPerHour;
  99. int        Foreground;
  100. int        Termlog;
  101. char    *Master;
  102. char    *MasterLog;
  103. char    *Collector;
  104. char    *Collector_Log;
  105. char    *Negotiator;
  106. char    *Negotiator_Log;
  107. char    *StartD;
  108. char    *Start_Log;
  109. char    *KbdD;
  110. char    *Kbd_Log;
  111. char    *SchedD;
  112. char    *Sched_Log;
  113. char    *CondorAdministrator;
  114.  
  115. int        NotFlag;
  116. int        PublishObituaries;
  117. int        X_runs_here;
  118. int        Lines;
  119.  
  120. usage( name )
  121. char    *name;
  122. {
  123.     dprintf( D_ALWAYS, "Usage: %s [-f] [-t] [-n]\n", name );
  124.     exit( 1 );
  125. }
  126.  
  127. DoCleanup()
  128. {
  129.     (void)signal( SIGCHLD, SIG_IGN );
  130.     do_killpg( Collector_Pid, SIGKILL );
  131.     do_killpg( Negotiator_Pid, SIGKILL );
  132.     do_killpg( StartD_Pid, SIGKILL );
  133.     do_killpg( KbdD_Pid, SIGKILL );
  134.     do_killpg( SchedD_Pid, SIGKILL );
  135. }
  136.  
  137.  
  138. main( argc, argv )
  139. int        argc;
  140. char    *argv[];
  141. {
  142.     struct itimerval    timer;
  143.     struct passwd        *pwd, *getpwnam();
  144.     char                **ptr, *startem;
  145.  
  146.     MyName = argv[0];
  147.  
  148.     if( getuid() != 0 ) {
  149.         dprintf( D_ALWAYS, "%s must be run as ROOT\n", MyName );
  150.         exit( 1 );
  151.     }
  152.  
  153.         /* Run as group condor so we can access log files even if they
  154.            are remotely mounted with NFS - needed because
  155.            root = nobody on the remote file system */
  156.     if( (pwd=getpwnam("condor")) == NULL ) {
  157.         EXCEPT( "condor not in passwd file" );
  158.     }
  159.     if( setgid(pwd->pw_gid) < 0 ) {
  160.         EXCEPT( "setgid(%d)", pwd->pw_gid );
  161.     }
  162.  
  163.     config( MyName, (CONTEXT *)0 );
  164.  
  165.     init_params();
  166.  
  167.     if( argc > 4 ) {
  168.         usage( argv[0] );
  169.     }
  170.     _EXCEPT_Cleanup = DoCleanup;
  171.  
  172.     for( ptr=argv+1; *ptr; ptr++ ) {
  173.         if( ptr[0][0] != '-' ) {
  174.             usage( argv[0] );
  175.         }
  176.         switch( ptr[0][1] ) {
  177.             case 'f':
  178.                 Foreground++;
  179.                 break;
  180.             case 't':
  181.                 Termlog++;
  182.                 break;
  183.             case 'n':
  184.                 NotFlag++;
  185.                 break;
  186.             default:
  187.                 usage( argv[0] );
  188.         }
  189.     }
  190.  
  191.     dprintf_config( "MASTER", 2 );
  192.  
  193.     startem = param("START_DAEMONS");
  194.     if( !startem || *startem == 'f' || *startem == 'F' ) {
  195.         dprintf( D_ALWAYS, "START_DAEMONS flag was set to %s.  Exiting.\n",
  196.             startem?startem:"(NULL)");
  197.         exit( 0 );
  198.     }
  199.  
  200.     if( !Termlog ) {
  201.         detach();
  202.     }
  203.  
  204.         /* Make sure we are the only copy of condor_master running */
  205.     get_lock( MasterLog );
  206.  
  207.     if( !Foreground ) {
  208.         if( fork() ) {
  209.             exit( 0 );
  210.         }
  211.     }
  212.  
  213.  
  214.     dprintf( D_ALWAYS,"*************************************************\n" );
  215.     dprintf( D_ALWAYS,"***          CONDOR_MASTER STARTING UP        ***\n" );
  216.     dprintf( D_ALWAYS,"***               PID = %-6d                ***\n",
  217.                                                                     getpid() );
  218.     dprintf( D_ALWAYS,"*************************************************\n" );
  219.  
  220.     if( signal(SIGALRM,sigalrm_handler) < 0 ) {
  221.         EXCEPT( "signal(SIGALRM,0x%x)", sigalrm_handler );
  222.     }
  223.  
  224.     if( signal(SIGCHLD,sigchld_handler) < 0 ) {
  225.         EXCEPT( "signal(SIGCHLD,0x%x)", sigchld_handler );
  226.     }
  227.  
  228.     if( signal(SIGINT,sigint_handler) < 0 ) {
  229.         EXCEPT( "signal(SIGINT,0x%x)", sigint_handler );
  230.     }
  231.  
  232.     if( signal(SIGQUIT,sigquit_handler) < 0 ) {
  233.         EXCEPT( "signal(SIGQUIT,0x%x)", sigquit_handler );
  234.     }
  235.  
  236.     if( signal(SIGHUP,sighup_handler) < 0 ) {
  237.         EXCEPT( "signal(SIGHUP,0x%x)", sighup_handler );
  238.     }
  239.  
  240.     if( signal(SIGUSR1,restart_master) < 0 ) {
  241.         EXCEPT( "signal(SIGUSR1,0x%x)", restart_master );
  242.     }
  243.  
  244.     start_all_daemons();
  245.  
  246.     timer.it_interval.tv_sec = HOUR / RestartsPerHour;
  247.     timer.it_interval.tv_usec = 0;
  248.     timer.it_value = timer.it_interval;
  249.     if( setitimer(ITIMER_REAL,&timer,(struct itimerval *)0) < 0 ) {
  250.         EXCEPT( "setitimer(ITIMER_REAL,0x%x,0)", &timer );
  251.     }
  252.  
  253.     for(;;) {
  254.         sigpause( 0 );
  255.     }
  256. }
  257.  
  258.  
  259. sigalrm_handler()
  260. {
  261.     KbdD_Restarts = MAX(0,KbdD_Restarts-1);
  262.     SchedD_Restarts = MAX(0,SchedD_Restarts-1);
  263.     StartD_Restarts = MAX(0,StartD_Restarts-1);
  264.     Collector_Restarts = MAX(0,Collector_Restarts-1);
  265.     Negotiator_Restarts = MAX(0,Negotiator_Restarts-1);
  266.  
  267.     if( NewExecutable(Master, &Master_TimeStamp) ) {
  268.         restart_master();
  269.     }
  270.  
  271.  
  272.     if( Collector_Pid && NewExecutable(Collector, &Collector_TimeStamp) ) {
  273.         dprintf(D_ALWAYS, "Collector was modified.  Killing %s\n", Collector);
  274.         do_killpg( Collector_Pid, SIGKILL );
  275.         Collector_Restarts = 0;
  276.     }
  277.  
  278.     if( Negotiator_Pid && NewExecutable(Negotiator, &Negotiator_TimeStamp) ) {
  279.         dprintf(D_ALWAYS, "Negotiator was modified.  Killing %s\n", Negotiator);
  280.         do_killpg( Negotiator_Pid, SIGKILL );
  281.         Negotiator_Restarts = 0;
  282.     }
  283.  
  284.     if( NewExecutable(KbdD, &KbdD_TimeStamp) ) {
  285.         dprintf(D_ALWAYS, "KbdD was modified.  Killing %s\n", KbdD);
  286.         do_killpg( KbdD_Pid, SIGKILL );
  287.         KbdD_Restarts = 0;
  288.     }
  289.  
  290.     if( NewExecutable(SchedD, &SchedD_TimeStamp) ) {
  291.         dprintf(D_ALWAYS, "SchedD was modified.  Killing %s\n", SchedD);
  292.         do_killpg( SchedD_Pid, SIGKILL );
  293.         SchedD_Restarts = 0;
  294.     }
  295.  
  296.     if( NewExecutable(StartD, &StartD_TimeStamp) ) {
  297.         dprintf(D_ALWAYS, "StartD was modified.  Killing %s\n", StartD);
  298.         do_killpg( StartD_Pid, SIGKILL );
  299.         StartD_Restarts = 0;
  300.     }
  301. }
  302.  
  303. restart_master()
  304. {
  305.     int            pid;
  306.  
  307.     dprintf(D_ALWAYS, "RESTARTING MASTER (new executable)\n");
  308.     (void)signal( SIGCHLD, SIG_IGN );
  309.     if( Collector_Pid ) {
  310.         do_killpg( Collector_Pid, SIGKILL );
  311.         dprintf(D_ALWAYS, "Killed Collector pid = %d\n", Collector_Pid );
  312.     }
  313.     if( Negotiator_Pid ) {
  314.         do_killpg( Negotiator_Pid, SIGKILL );
  315.         dprintf(D_ALWAYS, "Killed Negotiator pid = %d\n", Negotiator_Pid );
  316.     }
  317.     if( StartD_Pid ) {
  318.         do_killpg( StartD_Pid, SIGKILL );
  319.         dprintf(D_ALWAYS, "Killed StartD pid = %d\n", StartD_Pid );
  320.     }
  321.     if( KbdD_Pid ) {
  322.         do_killpg( KbdD_Pid, SIGKILL );
  323.         dprintf(D_ALWAYS, "Killed KbdD pid = %d\n", KbdD_Pid );
  324.     }
  325.     if( SchedD_Pid ) {
  326.         do_killpg( SchedD_Pid, SIGKILL );
  327.         dprintf(D_ALWAYS, "Killed SchedD pid = %d\n", SchedD_Pid );
  328.     }
  329.  
  330.         /* Wait until all children die */
  331.     for(;;) {
  332.         pid = wait( (union wait*)0 );
  333.         dprintf( D_ALWAYS, "Wait() returns pid %d\n", pid );
  334.         if( pid < 0 ) {
  335.             if( errno == ECHILD ) {
  336.                 break;
  337.             } else {
  338.                 EXCEPT( "wait( 0 )" );
  339.             }
  340.         }
  341.     }
  342.     dprintf( D_ALWAYS, "Done waiting for all children\n" );
  343.  
  344.     if( flock(MasterLockFD,LOCK_UN) < 0 ) {
  345.         dprintf( D_ALWAYS, "Can't remove lock on \"%s\"\n", MasterLog );
  346.         EXCEPT( "flock(%d,0%o)", MasterLockFD, LOCK_UN );
  347.     }
  348.     dprintf( D_ALWAYS, "Unlocked file descriptor %d\n", MasterLockFD );
  349.     (void)close( MasterLockFD );
  350.     dprintf( D_ALWAYS, "Closed file descriptor %d\n", MasterLockFD );
  351.  
  352.     dprintf( D_ALWAYS, "Doing exec( \"%s\", \"condor_master\", 0 )", Master );
  353.     (void)execl(Master, "condor_master", 0);
  354.     EXCEPT("execl(%s, condor_master, 0)", Master);
  355. }
  356.  
  357. #define IS_DAEMON(p) (p==SchedD_Pid||p==StartD_Pid|| \
  358.             p==Collector_Pid||p==Negotiator_Pid||p==KbdD_Pid)
  359.  
  360. sigchld_handler()
  361. {
  362.     int        pid = 0;
  363.     union wait    status;
  364.  
  365.     while( (pid=wait3(&status,WNOHANG,(struct rusage *)0)) != 0 ) {
  366.         if( pid == -1 ) {
  367.             EXCEPT( "wait3(0x%x,WNOHANG,0) returns %d", &status, pid );
  368.         }
  369.         if( WIFSTOPPED(status) ) {
  370.             continue;
  371.         }
  372.         if( !IS_DAEMON(pid) ) {
  373.             continue;
  374.         }
  375.         if( status.w_termsig != SIGKILL && PublishObituaries ) {
  376.             obituary( pid, &status );
  377.         }
  378.         restart( pid );
  379.         dprintf( D_ALWAYS | D_NOHEADER, "\n" );
  380.     }
  381. }
  382.  
  383. char *
  384. prog_log( pid )
  385. int        pid;
  386. {
  387.     if( pid == StartD_Pid ) {
  388.         return Start_Log;
  389.     }
  390.     if( pid == KbdD_Pid ) {
  391.         return Kbd_Log;
  392.     }
  393.     if( pid == SchedD_Pid ) {
  394.         return Sched_Log;
  395.     }
  396.     if( pid == Collector_Pid ) {
  397.         return Collector_Log;
  398.     }
  399.     if( pid == Negotiator_Pid ) {
  400.         return Negotiator_Log;
  401.     }
  402.     return "Unknown Program!!!";
  403. }
  404.  
  405. char *
  406. prog_name( pid )
  407. int        pid;
  408. {
  409.     if( pid == StartD_Pid ) {
  410.         return StartD;
  411.     }
  412.     if( pid == KbdD_Pid ) {
  413.         return KbdD;
  414.     }
  415.     if( pid == SchedD_Pid ) {
  416.         return SchedD;
  417.     }
  418.     if( pid == Collector_Pid ) {
  419.         return Collector;
  420.     }
  421.     if( pid == Negotiator_Pid ) {
  422.         return Negotiator;
  423.     }
  424.     return "Unknown Program!!!";
  425. }
  426.  
  427.  
  428. restart( pid )
  429. int        pid;
  430. {
  431.  
  432.  
  433.     if( pid == KbdD_Pid ) {
  434.         dprintf( D_ALWAYS, "The KbdD (process %d) died\n", pid );
  435.         do_killpg( pid, SIGKILL ) ;
  436.         if( ++KbdD_Restarts > RestartsPerHour ) {
  437.             give_up( KbdD );
  438.         }
  439.         KbdD_Pid = start_daemon( KbdD );
  440.     } else if( pid == SchedD_Pid ) {
  441.         dprintf( D_ALWAYS, "The SchedD (process %d) died\n", pid );
  442.         do_killpg( pid, SIGKILL ) ;
  443.         if( ++SchedD_Restarts > RestartsPerHour ) {
  444.             give_up( SchedD );
  445.         }
  446.         SchedD_Pid = start_daemon( SchedD );
  447.     } else if( pid == StartD_Pid ) {
  448.         dprintf( D_ALWAYS, "The StartD (process %d ) died\n", pid );
  449.         do_killpg( pid, SIGKILL ) ;
  450.         if( ++StartD_Restarts > RestartsPerHour ) {
  451.             give_up( StartD );
  452.         }
  453.         StartD_Pid = start_daemon( StartD );
  454.     } else if( pid == Collector_Pid ) {
  455.         dprintf( D_ALWAYS, "The Collector (process %d ) died\n", pid );
  456.         do_killpg( pid, SIGKILL ) ;
  457.         if( ++Collector_Restarts > RestartsPerHour ) {
  458.             give_up( Collector );
  459.         }
  460.         Collector_Pid = start_daemon( Collector );
  461.     } else if( pid == Negotiator_Pid ) {
  462.         dprintf( D_ALWAYS, "The Negotiator (process %d ) died\n", pid );
  463.         do_killpg( pid, SIGKILL ) ;
  464.         if( ++Negotiator_Restarts > RestartsPerHour ) {
  465.             give_up( Negotiator );
  466.         }
  467.         Negotiator_Pid = start_daemon( Negotiator );
  468.     } else {
  469.         dprintf( D_ALWAYS, "Child %d died, but not a daemon -- Ignored\n", pid);
  470.     }
  471. }
  472.  
  473. SetSyscalls(){}
  474.  
  475. init_params()
  476. {
  477.     char    *tmp;
  478.  
  479.     if( (Master = param("MASTER")) == NULL ) {
  480.         EXCEPT( "MASTER not specified in config file" );
  481.     }
  482.  
  483.     if( (MasterLog = param("MASTER_LOG")) == NULL ) {
  484.         EXCEPT( "MASTER_LOG not specified in config file" );
  485.     }
  486.  
  487.     if( (CollectorHost = param("COLLECTOR_HOST")) == NULL ) {
  488.         EXCEPT( "COLLECTOR_HOST not specified in config file" );
  489.     }
  490.  
  491.     if( (NegotiatorHost = param("NEGOTIATOR_HOST")) == NULL ) {
  492.         EXCEPT( "NEGOTIATOR_HOST not specified in config file" );
  493.     }
  494.  
  495.     if( (Collector = param("COLLECTOR")) == NULL ) {
  496.         EXCEPT( "COLLECTOR not specified in config file" );
  497.     }
  498.  
  499.     if( (Negotiator = param("NEGOTIATOR")) == NULL ) {
  500.         EXCEPT( "NEGOTIATOR not specified in config file" );
  501.     }
  502.  
  503.     if( (Collector_Log = param("COLLECTOR_LOG")) == NULL ) {
  504.         EXCEPT( "COLLECTOR_LOG not specified in config file" );
  505.     }
  506.  
  507.     if( (Negotiator_Log = param("NEGOTIATOR_LOG")) == NULL ) {
  508.         EXCEPT( "NEGOTIATOR_LOG not specified in config file" );
  509.     }
  510.  
  511.     if( (StartD = param("STARTD")) == NULL ) {
  512.         EXCEPT( "STARTD not specified in config file" );
  513.     }
  514.  
  515.     if( (Start_Log = param("STARTD_LOG")) == NULL ) {
  516.         EXCEPT( "STARTD_LOG not specified in config file" );
  517.     }
  518.  
  519.     if( (KbdD = param("KBDD")) == NULL ) {
  520.         EXCEPT( "KBDD not specified in config file" );
  521.     }
  522.  
  523.     if( (Kbd_Log = param("KBDD_LOG")) == NULL ) {
  524.         EXCEPT( "KBDD_LOG not specified in config file" );
  525.     }
  526.  
  527.     if( (SchedD = param("SCHEDD")) == NULL ) {
  528.         EXCEPT( "SCHEDD not specified in config file" );
  529.     }
  530.  
  531.     if( (Sched_Log = param("SCHEDD_LOG")) == NULL ) {
  532.         EXCEPT( "SCHEDD_LOG not specified in config file" );
  533.     }
  534.  
  535.     if( (CondorAdministrator = param("CONDOR_ADMIN")) == NULL ) {
  536.         EXCEPT( "CONDOR_ADMIN not specified in config file" );
  537.     }
  538.  
  539.     tmp = param("X_RUNS_HERE");
  540.     if( tmp && (*tmp == 't' || *tmp == 'T') ) {
  541.         X_runs_here = TRUE;
  542.     } else {
  543.         X_runs_here = FALSE;
  544.     }
  545.  
  546.     tmp = param("PUBLISH_OBITUARIES");
  547.     if( tmp && (*tmp == 't' || *tmp == 'T') ) {
  548.         PublishObituaries = TRUE;
  549.     } else {
  550.         PublishObituaries = FALSE;
  551.     }
  552.  
  553.     tmp = param("OBITUARY_LOG_LENGTH");
  554.     if( tmp == NULL ) {
  555.         Lines = 20;
  556.     } else {
  557.         Lines = atoi( tmp );
  558.     }
  559.  
  560.     tmp = param( "RESTARTS_PER_HOUR" );
  561.     if( tmp == NULL ) {
  562.         RestartsPerHour = 4;
  563.     } else {
  564.         RestartsPerHour = atoi( tmp );
  565.     }
  566.  
  567.     if( param("MASTER_DEBUG") ) {
  568.         if( boolean("MASTER_DEBUG","Foreground") ) {
  569.             Foreground++;
  570.         }
  571.     }
  572. }
  573.  
  574.  
  575. start_daemon( pathname )
  576. char    *pathname;
  577. {
  578.     int        pid;
  579.     char    *shortname;
  580.  
  581.     if( NotFlag ) {
  582.         dprintf( D_ALWAYS, "NOT Starting \"%s\"\n", pathname );
  583.         return 0;
  584.     }
  585.  
  586.     if( shortname = rindex(pathname,'/') ) {
  587.         shortname += 1;
  588.     } else {
  589.         shortname = pathname;
  590.     }
  591.  
  592.     if( access(pathname,X_OK) != 0 ) {
  593.         EXCEPT( "%s: Cannot execute" );
  594.     }
  595.  
  596.     if( (pid = vfork()) < 0 ) {
  597.         EXCEPT( "vfork()" );
  598.     }
  599.  
  600.     if( pid == 0 ) {    /* The child */
  601.         pid = getpid();
  602.         if( setpgrp(0,pid) < 0 ) {
  603.             EXCEPT( "setpgrp(0,%d)", pid );
  604.         }
  605.         (void)execl( pathname, shortname, "-f", 0 );
  606.         EXCEPT( "execl( %s, %s, -f, 0 )", pathname, shortname );
  607. #ifdef LINT
  608.         return 0;
  609. #endif LINT
  610.     } else {             /* The parent */
  611.         dprintf( D_ALWAYS, "Started \"%s\", pid and pgroup = %d\n",
  612.             shortname, pid );
  613.         return pid;
  614.     }
  615. }
  616.  
  617. collector_runs_here()
  618. {
  619.     char    hostname[512];
  620.     char    *my_host_name;
  621.     char    *mgr_host_name;
  622.     struct hostent    *hp, *gethostbyname();
  623.     
  624.         /* Get the "official" name of our own host */
  625.     if( gethostname(hostname,sizeof(hostname)) < 0 ) {
  626.         EXCEPT( "gethostname(0x%x,%d)", hostname, sizeof(hostname) );
  627.     }
  628.     if( (hp=gethostbyname(hostname)) == NULL ) {
  629.         EXCEPT( "gethostbyname(%s)", hostname );
  630.     }
  631.     my_host_name = strdup( hp->h_name );
  632.  
  633.         /* Get the "official" name of the collector host */
  634.     if( (hp=gethostbyname(CollectorHost)) == NULL ) {
  635.         EXCEPT( "gethostbyname(%s)", CollectorHost );
  636.     }
  637.     mgr_host_name = strdup( hp->h_name );
  638.  
  639.     return strcmp(my_host_name,mgr_host_name) == MATCH;
  640. }
  641.  
  642. negotiator_runs_here()
  643. {
  644.     char    hostname[512];
  645.     char    *my_host_name;
  646.     char    *mgr_host_name;
  647.     struct hostent    *hp, *gethostbyname();
  648.     
  649.         /* Get the "official" name of our own host */
  650.     if( gethostname(hostname,sizeof(hostname)) < 0 ) {
  651.         EXCEPT( "gethostname(0x%x,%d)", hostname, sizeof(hostname) );
  652.     }
  653.     if( (hp=gethostbyname(hostname)) == NULL ) {
  654.         EXCEPT( "gethostbyname(%s)", hostname );
  655.     }
  656.     my_host_name = strdup( hp->h_name );
  657.  
  658.         /* Get the "official" name of the negotiator host */
  659.     if( (hp=gethostbyname(NegotiatorHost)) == NULL ) {
  660.         EXCEPT( "gethostbyname(%s)", NegotiatorHost );
  661.     }
  662.     mgr_host_name = strdup( hp->h_name );
  663.  
  664.     return strcmp(my_host_name,mgr_host_name) == MATCH;
  665. }
  666.  
  667. obituary( pid, status )
  668. int            pid;
  669. union wait    *status;
  670. {
  671.     char    cmd[512];
  672.     char    hostname[512];
  673.     FILE    *mailer, *popen();
  674.     char    *name, *log;
  675.  
  676.  
  677.         /* If daemon with a serious bug gets installed, we may end up
  678.         ** doing many restarts in rapid succession.  In that case, we
  679.         ** don't want to send repeated mail to the CONDOR administrator.
  680.         ** This could overwhelm the administrator's machine.
  681.         */
  682.     if( pid == KbdD_Pid ) {
  683.         if( KbdD_Restarts > 1 ) {
  684.             return;
  685.         }
  686.     } else if( pid == SchedD_Pid ) {
  687.         if( SchedD_Restarts > 1 ) {
  688.             return;
  689.         }
  690.     } else if( pid == StartD_Pid ) {
  691.         if( StartD_Restarts > 1 ) {
  692.             return;
  693.         }
  694.     } else if( pid == Collector_Pid ) {
  695.         if( Collector_Restarts > 1 ) {
  696.             return;
  697.         }
  698.     } else if( pid == Negotiator_Pid ) {
  699.         if( Negotiator_Restarts > 1 ) {
  700.             return;
  701.         }
  702.     } else {
  703.         EXCEPT( "Pid %d returned by wait3(), but not a child\n", pid );
  704.     }
  705.  
  706.  
  707.     name = prog_name( pid );
  708.     log = prog_log( pid );
  709.  
  710.     dprintf( D_ALWAYS, "Sending obituary for \"%s\" to \"%s\"\n",
  711.                                                 name, CondorAdministrator );
  712.  
  713.     if( gethostname(hostname,sizeof(hostname)) < 0 ) {
  714.         EXCEPT( "gethostname(0x%x,%d)", hostname, sizeof(hostname) );
  715.     }
  716.  
  717.     (void)sprintf( cmd, "/bin/mail %s", CondorAdministrator );
  718.     if( (mailer=popen(cmd,"w")) == NULL ) {
  719.         EXCEPT( "popen(\"%s\",\"w\")", cmd );
  720.     }
  721.  
  722.     fprintf( mailer, "To: %s\n", CondorAdministrator );
  723.     fprintf( mailer, "Subject: CONDOR Problem\n" );
  724.     fprintf( mailer, "\n" );
  725.  
  726.     if( status->w_termsig ) {
  727.         fprintf( mailer, "\"%s\" on \"%s\" died due to signal %d\n",
  728.                                     name, hostname, status->w_termsig );
  729.         fprintf( mailer, "(%s core was produced)\n",
  730.                                     status->w_coredump ? "a" : "no" );
  731.     } else {
  732.         fprintf( mailer,
  733.         "\"%s\" on \"%s\" exited with staus %d\n",
  734.                                     name, hostname, status->w_retcode );
  735.     }
  736.     tail_log( mailer, log, Lines );
  737.  
  738.         /* Don't do a pclose here, it wait()'s, and may steal an
  739.         ** exit notification of one of our daemons.  Instead we'll clean
  740.         ** up popen's child in our SIGCHLD handler.
  741.         */
  742.     (void)fclose( mailer );
  743. }
  744.  
  745. tail_log( output, file, lines )
  746. FILE    *output;
  747. char    *file;
  748. int        lines;
  749. {
  750.     FILE    *input;
  751.     int        ch, last_ch;
  752.     long    loc, ftell();
  753.     QUEUE    queue, *q = &queue;
  754.  
  755.     if( (input=fopen(file,"r")) == NULL ) {
  756.         fprintf( stderr, "Can't open %s\n", file );
  757.         return;
  758.     }
  759.  
  760.     init_queue( q, lines );
  761.     last_ch = '\n';
  762.  
  763.     while( (ch=getc(input)) != EOF ) {
  764.         if( last_ch == '\n' && ch != '\n' ) {
  765.             insert_queue( q, ftell(input) - 1 );
  766.         }
  767.         last_ch = ch;
  768.     }
  769.  
  770.  
  771.     while( !empty_queue( q ) ) {
  772.         loc = delete_queue( q );
  773.         display_line( loc, input, output );
  774.     }
  775.     (void)fclose( input );
  776. }
  777.  
  778. display_line( loc, input, output )
  779. long    loc;
  780. FILE    *input;
  781. FILE    *output;
  782. {
  783.     int        ch;
  784.  
  785.     (void)fseek( input, loc, 0 );
  786.  
  787.     for(;;) {
  788.         ch = getc(input);
  789.         (void)putc( ch, output );
  790.         if( ch == EOF || ch == '\n' ) {
  791.             return;
  792.         }
  793.     }
  794. }
  795.  
  796. init_queue( queue, size )
  797. QUEUE    *queue;
  798. {
  799.     queue->first = 0;
  800.     queue->last = 0;
  801.     queue->size = size;
  802.     queue->n_elem = 0;
  803. }
  804.  
  805. insert_queue( queue, elem )
  806. QUEUE    *queue;
  807. long    elem;
  808. {
  809.     if( queue->n_elem == queue->size ) {
  810.         queue->first = (queue->first + 1) % (queue->size + 1);
  811.     } else {
  812.         queue->n_elem += 1;
  813.     }
  814.     queue->data[queue->last] = elem;
  815.     queue->last = (queue->last + 1) % (queue->size + 1);
  816. }
  817.  
  818. long
  819. delete_queue( queue )
  820. QUEUE    *queue;
  821. {
  822.     long    answer;
  823.  
  824.     queue->n_elem -= 1;
  825.     answer = queue->data[ queue->first ];
  826.     queue->first = (queue->first + 1) % (queue->size + 1);
  827.     return answer;
  828. }
  829.  
  830. empty_queue( queue )
  831. QUEUE    *queue;
  832. {
  833.     return queue->first == queue->last;
  834. }
  835.  
  836.  
  837. give_up( name )
  838. char    *name;
  839. {
  840.     char    cmd[512];
  841.     char    hostname[512];
  842.     FILE    *mailer, *popen();
  843.  
  844.     dprintf( D_ALWAYS, "Exceeded %d restarts / hour on \"%s\"\n",
  845.                                                     RestartsPerHour, name );
  846.     dprintf( D_ALWAYS, "Sending mail to \"%s\"\n", CondorAdministrator );
  847.  
  848.     if( gethostname(hostname,sizeof(hostname)) < 0 ) {
  849.         EXCEPT( "gethostname(0x%x,%d)", hostname, sizeof(hostname) );
  850.     }
  851.  
  852.     (void)sprintf( cmd, "/bin/mail %s", CondorAdministrator );
  853.     if( (mailer=popen(cmd,"w")) == NULL ) {
  854.         EXCEPT( "popen(\"%s\",\"w\")", cmd );
  855.     }
  856.  
  857.     fprintf( mailer, "To: %s\n", CondorAdministrator );
  858.     fprintf( mailer, "Subject: CONDOR Problem\n" );
  859.     fprintf( mailer, "\n" );
  860.  
  861.     fprintf( mailer, "HELP!\n\n" );
  862.     fprintf( mailer,
  863.     "The CONDOR_DaemonMaster on [%s] has exceeded %d restarts/hour for [%s]\n",
  864.             hostname, RestartsPerHour, name);
  865.  
  866.     (void)pclose( mailer );
  867.  
  868.     (void)signal( SIGCHLD, SIG_IGN );
  869.     do_killpg( Collector_Pid, SIGKILL );
  870.     do_killpg( Negotiator_Pid, SIGKILL );
  871.     do_killpg( StartD_Pid, SIGKILL );
  872.     do_killpg( KbdD_Pid, SIGKILL );
  873.     do_killpg( SchedD_Pid, SIGKILL );
  874.     dprintf( D_ALWAYS, "*** E X I T I N G ***\n\n" );
  875.     exit( 1 );
  876. }
  877.  
  878. get_lock( file_name )
  879. char    *file_name;
  880. {
  881.     if( (MasterLockFD=open(file_name,0,0)) < 0 ) {
  882.         EXCEPT( "open(%s,0,0)", file_name );
  883.     }
  884.  
  885.     if( flock(MasterLockFD,LOCK_EX|LOCK_NB) < 0 ) {
  886.         dprintf( D_ALWAYS, "Can't get lock on file \"%s\"\n", file_name );
  887.         EXCEPT( "flock(%d,0%o)", MasterLockFD, LOCK_EX | LOCK_NB );
  888.     }
  889. }
  890.  
  891.  
  892. do_killpg( pgrp, sig )
  893. int        pgrp;
  894. int        sig;
  895. {
  896.     if( !pgrp ) {
  897.         return;
  898.     }
  899.  
  900.     if( sig < 0 || sig >= NSIG ) {
  901.         EXCEPT( "Unknown signal (%d)", sig );
  902.     }
  903.  
  904.     (void) killpg( pgrp, sig );
  905.     dprintf( D_ALWAYS, "Sent %s to process group %d\n", SigNames[sig], pgrp );
  906. }
  907.  
  908. do_kill( pid, sig )
  909. int        pid;
  910. int        sig;
  911. {
  912.     if( !pid ) {
  913.         return;
  914.     }
  915.  
  916.     if( kill(pid,sig) < 0 ) {
  917.         EXCEPT( "kill(%d,%d)", pid, sig );
  918.     }
  919.     dprintf( D_ALWAYS, "Sent %s to process %d\n", SigNames[sig], pid );
  920. }
  921.  
  922. /*
  923. ** Re read the config file, and send all the daemons a signal telling
  924. ** them to do so also.
  925. */
  926. sighup_handler()
  927. {
  928.     dprintf( D_ALWAYS, "Re reading config file\n" );
  929.     config( MyName, (CONTEXT *)0 );
  930.     init_params();
  931.     do_kill( Collector_Pid, SIGHUP );
  932.     do_kill( Negotiator_Pid, SIGHUP );
  933.     do_kill( StartD_Pid, SIGHUP );
  934.     do_kill( KbdD_Pid, SIGHUP );
  935.     do_kill( SchedD_Pid, SIGHUP );
  936.     dprintf( D_ALWAYS | D_NOHEADER, "\n" );
  937. }
  938.  
  939. /*
  940. ** Kill and restart all daemons.
  941. */
  942. sigint_handler()
  943. {
  944.     dprintf( D_ALWAYS, "Killing all daemons\n" );
  945.     (void)signal( SIGCHLD, SIG_IGN );
  946.     do_killpg( Collector_Pid, SIGKILL );
  947.     do_killpg( Negotiator_Pid, SIGKILL );
  948.     do_killpg( StartD_Pid, SIGKILL );
  949.     do_killpg( KbdD_Pid, SIGKILL );
  950.     do_killpg( SchedD_Pid, SIGKILL );
  951.     dprintf( D_ALWAYS, "Restarting all daemons\n" );
  952.     sleep( 5 );    /* NOT a good way to do this... */
  953.     if( signal(SIGCHLD,sigchld_handler) < 0 ) {
  954.         EXCEPT( "signal(SIGCHLD,0x%x)", sigchld_handler );
  955.     }
  956.     start_all_daemons();
  957. }
  958. /*
  959. ** Kill all daemons and go away.
  960. */
  961. sigquit_handler()
  962. {
  963.     (void)signal( SIGCHLD, SIG_IGN );
  964.     do_killpg( Collector_Pid, SIGKILL );
  965.     do_killpg( Negotiator_Pid, SIGKILL );
  966.     do_killpg( StartD_Pid, SIGKILL );
  967.     do_killpg( KbdD_Pid, SIGKILL );
  968.     do_killpg( SchedD_Pid, SIGKILL );
  969.     dprintf( D_ALWAYS, "Killed by SIGQUIT\n" );
  970.     exit( 0 );
  971. }
  972.  
  973. start_all_daemons()
  974. {
  975.     Master_TimeStamp = GetTimeStamp( Master );
  976.  
  977.     if( collector_runs_here() ) {
  978.         Collector_Pid = start_daemon( Collector );
  979.         Collector_TimeStamp = GetTimeStamp( Collector );
  980.     }
  981.  
  982.     if( negotiator_runs_here() ) {
  983.         Negotiator_Pid = start_daemon( Negotiator );
  984.         Negotiator_TimeStamp = GetTimeStamp( Negotiator );
  985.     }
  986.  
  987.     if( X_runs_here ) {
  988.         KbdD_Pid = start_daemon( KbdD );
  989.         KbdD_TimeStamp = GetTimeStamp( KbdD );
  990.     }
  991.  
  992.     StartD_Pid = start_daemon( StartD );
  993.     StartD_TimeStamp = GetTimeStamp( StartD );
  994.  
  995.     SchedD_Pid = start_daemon( SchedD );
  996.     SchedD_TimeStamp = GetTimeStamp( SchedD );
  997.  
  998.     dprintf( D_ALWAYS | D_NOHEADER, "\n" );
  999. }
  1000.  
  1001. time_t
  1002. GetTimeStamp(file)
  1003. char *file;
  1004. {
  1005.     struct stat sbuf;
  1006.  
  1007.     if( stat(file, &sbuf) < 0 ) {
  1008.         return( (time_t) -1 );
  1009.     }
  1010.  
  1011.     return( sbuf.st_mtime );
  1012. }
  1013.  
  1014. NewExecutable(file, tsp)
  1015. char *file;
  1016. time_t *tsp;
  1017. {
  1018.     time_t cts = GetTimeStamp(file);
  1019.  
  1020.     if( cts == (time_t) -1 ) {
  1021.         /*
  1022.         **    We could have been in the process of installing a new
  1023.         **    version, and that's why the 'stat' failed.  Catch it
  1024.         **  next time around.
  1025.         */
  1026.         return( FALSE );
  1027.     }
  1028.  
  1029.     if( cts != *tsp ) {
  1030.         *tsp = cts;
  1031.         return( TRUE );
  1032.     }
  1033.  
  1034.     return FALSE;
  1035. }
  1036.