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_startd / startd.c < prev    next >
C/C++ Source or Header  |  1989-09-14  |  11KB  |  522 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 <netdb.h>
  31. #include <errno.h>
  32. #include <pwd.h>
  33. #include <signal.h>
  34. #include <ctype.h>
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <sys/param.h>
  38. #include <sys/file.h>
  39. #include <sys/time.h>
  40. #include <sys/resource.h>
  41. #include <sys/wait.h>
  42. #include <netinet/in.h>
  43. #include <rpc/types.h>
  44. #include <rpc/xdr.h>
  45.  
  46. #include "condor_types.h"
  47. #include "debug.h"
  48. #include "trace.h"
  49. #include "except.h"
  50. #include "sched.h"
  51. #include "expr.h"
  52. #include "clib.h"
  53.  
  54. static char *_FileName_ = __FILE__;        /* Used by EXCEPT (see except.h)     */
  55.  
  56. CONTEXT    *create_context();
  57. extern struct sockaddr_in   From;
  58.  
  59. extern int    errno;
  60.  
  61. char    *param();
  62. int        reaper();
  63.  
  64. CONTEXT    *MachineContext;
  65. CONTEXT *JobContext;
  66.  
  67. int    FrgnJobsRunning;
  68.  
  69. char    ThisHost[512];
  70. char    XSockName[512];
  71.  
  72. char    *Log;
  73. int        PollingFrequency;
  74. int        PollsPerUpdate;
  75. char    *Execute;
  76. char    *Starter;
  77. char    *CollectorHost;
  78. char    *CondorAdministrator;
  79. int        Foreground;
  80. int        Termlog;
  81. int        Memory;
  82. char    *Spool;
  83. int        State;
  84.  
  85. int        On = 1;
  86.  
  87. #ifdef vax
  88. struct linger linger = { 0, 0 };    /* Don't linger */
  89. #endif vax
  90.  
  91. int        ConnectionSock;
  92. int        UdpSock;    /* Send datagrams to the collector */
  93. int        UdpIn;        /* Get datagrams from the keyboard daemon */
  94.  
  95. extern int    Terse;
  96. int    LastTimeout;
  97.  
  98. char *MyName;
  99.  
  100. usage( name )
  101. char    *name;
  102. {
  103.     dprintf( D_ALWAYS, "Usage: %s [-f] [-t]\n", name );
  104.     exit( 1 );
  105. }
  106.  
  107. main( argc, argv)
  108. int        argc;
  109. char    *argv[];
  110. {
  111.     int        count;
  112.     fd_set    readfds;
  113.     struct timeval    timer;
  114.     char    **ptr;
  115.     int        sigint_handler(), sighup_handler(), abort();
  116.  
  117.  
  118.         /* Read the configuration file */
  119.  
  120.     MachineContext = create_context();
  121.  
  122.     MyName = *argv;
  123.     config( MyName, MachineContext );
  124.     init_params();
  125.     Terse = 1;
  126.  
  127.     cleanup_execute_dir();
  128.  
  129.     if( argc > 3 ) {
  130.         usage( argv[0] );
  131.     }
  132.     for( ptr=argv+1; *ptr; ptr++ ) {
  133.         if( ptr[0][0] != '-' ) {
  134.             usage( argv[0] );
  135.         }
  136.         switch( ptr[0][1] ) {
  137.             case 'f':
  138.                 Foreground++;
  139.                 break;
  140.             case 't':
  141.                 Termlog++;
  142.                 break;
  143.             default:
  144.                 usage( argv[0] );
  145.         }
  146.     }
  147.  
  148.         /* This is so if we dump core it'll go in the log directory */
  149.     if( chdir(Log) < 0 ) {
  150.         EXCEPT( "chdir to log directory <%s>", Log );
  151.     }
  152.  
  153.         /* Arrange to run in background */
  154.     if( !Foreground ) {
  155.         if( fork() )
  156.             exit( 0 );
  157.     }
  158.  
  159.         /* Set up logging */
  160.     dprintf_config( "STARTD", 2 );
  161.  
  162.     dprintf( D_ALWAYS, "**************************************************\n" );
  163.     dprintf( D_ALWAYS, "***          CONDOR_STARTD STARTING UP         ***\n" );
  164.     dprintf( D_ALWAYS, "**************************************************\n" );
  165.     dprintf( D_ALWAYS, "\n" );
  166.  
  167.     if( getuid() != 0 ) {
  168.         EXCEPT("The start daemon must be run as root");
  169.     }
  170.  
  171.     if( signal(SIGINT,sigint_handler) < 0 ) {
  172.         EXCEPT( "signal(SIGINT,0x%x)", sigint_handler );
  173.     }
  174.     if( signal(SIGHUP,sighup_handler) < 0 ) {
  175.         EXCEPT( "signal(SIGHUP,0x%x)", sighup_handler );
  176.     }
  177.     if( signal(SIGPIPE,SIG_IGN) < 0 ) {
  178.         EXCEPT( "signal(SIGPIPE,SIG_IGN)" );
  179.     }
  180.     /*
  181.     if( signal(SIGALRM,abort) < 0 ) {
  182.         EXCEPT( "signal(SIGALRM,abort)" );
  183.     }
  184.     */
  185.  
  186.     ConnectionSock = init_connection_sock( "condor_startd", START_PORT );
  187.     UdpIn = init_udp_sock( "condor_startd", START_UDP_PORT );
  188.     UdpSock = udp_connect( CollectorHost, COLLECTOR_UDP_PORT );
  189.  
  190.     if( signal(SIGCHLD,reaper) < 0 ) {
  191.         EXCEPT( "signal(SIGCHLD,reaper)" );
  192.     }
  193.  
  194.     if( gethostname(ThisHost,sizeof ThisHost) < 0 ) {
  195.         EXCEPT( "gethostname" );
  196.     }
  197.     (void)sprintf( XSockName, "%s:0", ThisHost );
  198.  
  199.    get_k_vars();   /* prepare to read kernel's process table */
  200.  
  201.     LastTimeout = (int)time( (time_t *)0 );
  202.     timer.tv_usec = 0;
  203.  
  204.     change_states( NO_JOB );
  205.     timeout();
  206.     FD_ZERO( &readfds );
  207.  
  208.     for(;;) {
  209.  
  210.         FD_SET( ConnectionSock, &readfds );
  211.         FD_SET( UdpIn, &readfds );
  212.         timer.tv_sec = PollingFrequency -
  213.                                     ( (int)time((time_t *)0) - LastTimeout );
  214.         if( timer.tv_sec < 0 ) {
  215.             timer.tv_sec = 0;
  216.         }
  217.  
  218.         count = select(FD_SETSIZE, (int *)&readfds, (int *)0, (int *)0,
  219.                                                 (struct timeval *)&timer );
  220.         /*
  221.         ** count = select(FD_SETSIZE, &readfds, 0, 0, 0 );
  222.         */
  223.  
  224.         if( count < 0 ) {
  225.             if( errno == EINTR ) {
  226.                 continue;
  227.             } else {
  228.                 EXCEPT( "select(FD_SETSIZE,0%o,0,0,%d sec)",
  229.                                                 readfds, timer.tv_sec );
  230.             }
  231.         }
  232.  
  233.         (void)sigblock( sigmask(SIGCHLD) );     /* Block out SIGCHLD */
  234.         if( count == 0 ) {
  235.             timeout();
  236.         }
  237.         if( FD_ISSET(ConnectionSock,&readfds) ) {
  238.             accept_connection();
  239.         }
  240.         if( FD_ISSET(UdpIn,&readfds) ) {
  241.             accept_datagram();
  242.         }
  243.         (void)sigsetmask( 0 );            /* Allow SIGCHLD */
  244.     }
  245. }
  246.  
  247. accept_connection()
  248. {
  249.     struct sockaddr_in    from;
  250.     int        len;
  251.     int        fd;
  252.     XDR        xdr, *xdrs, *xdr_Init();
  253.  
  254.     len = sizeof from;
  255.     bzero( (char *)&from, sizeof from );
  256.     fd = accept( ConnectionSock, (struct sockaddr *)&from, &len );
  257.  
  258.     if( fd < 0 && errno != EINTR ) {
  259.         EXCEPT( "accept" );
  260.     }
  261.  
  262.     if( fd >= 0 ) {
  263.         xdrs = xdr_Init( &fd, &xdr );
  264.         do_command( xdrs, &from );
  265.         xdr_destroy( xdrs );
  266.         (void)close( fd );
  267.     }
  268. }
  269.  
  270. accept_datagram()
  271. {
  272.     XDR     xdr, *xdrs, *xdr_Udp_Init();
  273.     int     cmd;
  274.  
  275.  
  276.     xdrs = xdr_Udp_Init( &UdpIn, &xdr );
  277.  
  278.     do_command( xdrs, &From );
  279.  
  280.     xdr_destroy( xdrs );
  281. }
  282.  
  283.  
  284. init_connection_sock( service, port )
  285. char    *service;
  286. int        port;
  287. {
  288.     struct sockaddr_in    sin;
  289.     struct servent *servp;
  290.     int        sock;
  291.  
  292.     bzero( (char *)&sin, sizeof sin );
  293.     servp = getservbyname(service, "tcp");
  294.     if( servp ) {
  295.         sin.sin_port = htons( (u_short)servp->s_port );
  296.     } else {
  297.         sin.sin_port = htons( (u_short)port );
  298.     }
  299.  
  300.     if( (sock=socket(AF_INET,SOCK_STREAM,0)) < 0 ) {
  301.         EXCEPT( "socket" );
  302.     }
  303.  
  304.     if( setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(caddr_t *)&On,sizeof(On))< 0) {
  305.         EXCEPT( "setsockopt" );
  306.     }
  307.  
  308. #ifdef vax
  309.     if( setsockopt(sock,SOL_SOCKET,SO_LINGER,&linger,sizeof(linger)) < 0 ) {
  310.         EXCEPT( "setsockopt" );
  311.     }
  312. #endif vax
  313.  
  314.     if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
  315.         if( errno == EADDRINUSE ) {
  316.             EXCEPT( "CONDOR_STARTD ALREADY RUNNING" );
  317.         } else {
  318.             EXCEPT( "bind" );
  319.         }
  320.     }
  321.  
  322.     if( listen(sock,5) < 0 ) {
  323.         EXCEPT( "listen" );
  324.     }
  325.  
  326.     return sock;
  327. }
  328.  
  329. reaper()
  330. {
  331.     int        pid;
  332.     union wait    status;
  333.     struct rusage rusage;
  334.  
  335.     while( (pid = wait3(&status,WNOHANG|WUNTRACED,&rusage)) > 0 )  {
  336.  
  337.         if( WIFSTOPPED(status) ) {
  338.             dprintf( D_ALWAYS, "Starter %d has stopped\n", pid );
  339.             return;
  340.         }
  341.         if( WIFSIGNALED(status) ) {
  342.             dprintf( D_ALWAYS, "Starter %d died on signal %d\n",
  343.                                         pid, status.w_termsig );
  344.         } else {
  345.             dprintf( D_ALWAYS, "Starter %d exited with status %d\n",
  346.                                             pid, status.w_retcode );
  347.         }
  348.         job_dies();
  349.     }
  350. }
  351.  
  352. /*
  353. ** Somebody has connected to our socket with a request.  Read the request
  354. ** and handle it.
  355. */
  356. do_command( xdrs, from )
  357. XDR        *xdrs;
  358. struct sockaddr_in    *from;
  359. {
  360.     int        cmd;
  361.  
  362.         /* Read the request */
  363.     xdrs->x_op = XDR_DECODE;
  364.     if( !xdr_int(xdrs,&cmd) ) {
  365.         dprintf( D_ALWAYS, "Can't read command\n" );
  366.         return;
  367.     }
  368.  
  369.     switch( cmd ) {
  370.         case START_FRGN_JOB:    /* Request from foreign shadow to start a job */
  371.             start_job_request( xdrs, from );
  372.             break;
  373.         case CKPT_FRGN_JOB:
  374.             vacate_order();
  375.             break;
  376.         case KILL_FRGN_JOB:
  377.             kill_job( OK );
  378.             break;
  379.         case X_EVENT_NOTIFICATION:
  380.             x_event();
  381.             break;
  382.         default:
  383.             EXCEPT( "Got unknown command (%d)\n", cmd );
  384.     }
  385. }
  386.  
  387. SetSyscalls(){}
  388.  
  389. init_params()
  390. {
  391.     char    *pval;
  392.     char    *tmp;
  393.  
  394.     Log = param( "LOG" );
  395.     if( Log == NULL )  {
  396.         EXCEPT( "No log directory specified in config file\n" );
  397.     }
  398.  
  399.     Execute = param( "EXECUTE" );
  400.     if( Execute == NULL ) {
  401.         EXCEPT( "No Execute file specified in config file\n" );
  402.     }
  403.  
  404.     Starter = param( "STARTER" );
  405.     if( Starter == NULL ) {
  406.         EXCEPT( "No Starter file specified in config file\n" );
  407.     }
  408.  
  409.     CollectorHost = param( "COLLECTOR_HOST" );
  410.     if( CollectorHost == NULL ) {
  411.         EXCEPT( "No Collector host specified in config file\n" );
  412.     }
  413.  
  414.     tmp = param( "POLLING_FREQUENCY" );
  415.     if( tmp == NULL ) {
  416.         PollingFrequency = 30;
  417.     } else {
  418.         PollingFrequency = atoi( tmp );
  419.     }
  420.  
  421.     tmp = param( "POLLS_PER_UPDATE" );
  422.     if( tmp == NULL ) {
  423.         PollsPerUpdate = 4;
  424.     } else {
  425.         PollsPerUpdate = atoi( tmp );
  426.     }
  427.  
  428.     if( param("STARTD_DEBUG") == NULL ) {
  429.         EXCEPT( "STARTD_DEBUG not defined in config file\n" );
  430.     }
  431.     Foreground = boolean( "STARTD_DEBUG", "Foreground" );
  432.  
  433.     if( (CondorAdministrator = param("CONDOR_ADMIN")) == NULL ) {
  434.         EXCEPT( "CONDOR_ADMIN not specified in config file" );
  435.     }
  436.  
  437.     pval = param("MEMORY");
  438.     if( pval != NULL ) {
  439.         Memory = atoi( pval );
  440.     }
  441.     if( Memory <= 0 || Memory >= 500 ) {
  442.         Memory =  DEFAULT_MEMORY;
  443.     }
  444.  
  445.     if( (Spool = param("SPOOL")) == NULL ) {
  446.         EXCEPT( "SPOOL not specified in config file" );
  447.     }
  448.  
  449. }
  450.  
  451. sigint_handler()
  452. {
  453.     dprintf( D_ALWAYS, "Killed by SIGINT\n" );
  454.     exit( 0 );
  455. }
  456.  
  457. sighup_handler()
  458. {
  459.     dprintf( D_ALWAYS, "Re reading config file\n" );
  460.  
  461.     free_context( MachineContext );
  462.     MachineContext = create_context();
  463.     config( MyName, MachineContext );
  464.     init_params();
  465. }
  466.  
  467. cleanup_execute_dir()
  468. {
  469.      char *execute, *rindex();
  470.      char buf[ 1024 ];
  471.  
  472.     execute = rindex(Execute, '/');
  473.     if( execute == NULL ) {
  474.         execute = Execute;
  475.     } else {
  476.         execute++;
  477.     }
  478.  
  479.     if( strcmp("execute", execute) != 0 ) {
  480.         EXCEPT("EXECUTE parameter (%s) must end with 'execute'.\n", Execute);
  481.     }
  482.  
  483.     /* Take this out temporarily so we can get a core of the starter...
  484.     (void)sprintf(buf, "rm -f %s/*", Execute);
  485.     */
  486.  
  487.     (void)sprintf(buf, "rm -f %s/condor_exec*", Execute);
  488.     (void)system(buf);
  489.  
  490. }
  491.  
  492. init_udp_sock( service, port )
  493. char    *service;
  494. int     port;
  495. {
  496.     struct sockaddr_in  sin;
  497.     struct servent *servp;
  498.     int     sock;
  499.  
  500.     bzero( (char *)&sin, sizeof sin );
  501.     servp = getservbyname(service, "tcp");
  502.     if( servp ) {
  503.         sin.sin_port = htons( (u_short)servp->s_port );
  504.     } else {
  505.         sin.sin_port = htons( (u_short)port );
  506.     }
  507.  
  508.     if( (sock=socket(AF_INET,SOCK_DGRAM,0)) < 0 ) {
  509.         EXCEPT( "socket" );
  510.     }
  511.  
  512.     if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
  513.         if( errno == EADDRINUSE ) {
  514.             EXCEPT( "CONDOR_COLLECTOR ALREADY RUNNING" );
  515.         } else {
  516.             EXCEPT( "bind" );
  517.         }
  518.     }
  519.  
  520.     return sock;
  521. }
  522.