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 >
Wrap
C/C++ Source or Header
|
1989-09-14
|
11KB
|
522 lines
/*
** Copyright 1986, 1987, 1988, 1989 University of Wisconsin
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the name of the University of
** Wisconsin not be used in advertising or publicity pertaining to
** distribution of the software without specific, written prior
** permission. The University of Wisconsin makes no representations about
** the suitability of this software for any purpose. It is provided "as
** is" without express or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN DISCLAIMS ALL WARRANTIES WITH REGARD TO
** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
** FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN BE LIABLE FOR
** ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**
** Authors: Allan Bricker and Michael J. Litzkow,
** University of Wisconsin, Computer Sciences Dept.
**
*/
#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include "condor_types.h"
#include "debug.h"
#include "trace.h"
#include "except.h"
#include "sched.h"
#include "expr.h"
#include "clib.h"
static char *_FileName_ = __FILE__; /* Used by EXCEPT (see except.h) */
CONTEXT *create_context();
extern struct sockaddr_in From;
extern int errno;
char *param();
int reaper();
CONTEXT *MachineContext;
CONTEXT *JobContext;
int FrgnJobsRunning;
char ThisHost[512];
char XSockName[512];
char *Log;
int PollingFrequency;
int PollsPerUpdate;
char *Execute;
char *Starter;
char *CollectorHost;
char *CondorAdministrator;
int Foreground;
int Termlog;
int Memory;
char *Spool;
int State;
int On = 1;
#ifdef vax
struct linger linger = { 0, 0 }; /* Don't linger */
#endif vax
int ConnectionSock;
int UdpSock; /* Send datagrams to the collector */
int UdpIn; /* Get datagrams from the keyboard daemon */
extern int Terse;
int LastTimeout;
char *MyName;
usage( name )
char *name;
{
dprintf( D_ALWAYS, "Usage: %s [-f] [-t]\n", name );
exit( 1 );
}
main( argc, argv)
int argc;
char *argv[];
{
int count;
fd_set readfds;
struct timeval timer;
char **ptr;
int sigint_handler(), sighup_handler(), abort();
/* Read the configuration file */
MachineContext = create_context();
MyName = *argv;
config( MyName, MachineContext );
init_params();
Terse = 1;
cleanup_execute_dir();
if( argc > 3 ) {
usage( argv[0] );
}
for( ptr=argv+1; *ptr; ptr++ ) {
if( ptr[0][0] != '-' ) {
usage( argv[0] );
}
switch( ptr[0][1] ) {
case 'f':
Foreground++;
break;
case 't':
Termlog++;
break;
default:
usage( argv[0] );
}
}
/* This is so if we dump core it'll go in the log directory */
if( chdir(Log) < 0 ) {
EXCEPT( "chdir to log directory <%s>", Log );
}
/* Arrange to run in background */
if( !Foreground ) {
if( fork() )
exit( 0 );
}
/* Set up logging */
dprintf_config( "STARTD", 2 );
dprintf( D_ALWAYS, "**************************************************\n" );
dprintf( D_ALWAYS, "*** CONDOR_STARTD STARTING UP ***\n" );
dprintf( D_ALWAYS, "**************************************************\n" );
dprintf( D_ALWAYS, "\n" );
if( getuid() != 0 ) {
EXCEPT("The start daemon must be run as root");
}
if( signal(SIGINT,sigint_handler) < 0 ) {
EXCEPT( "signal(SIGINT,0x%x)", sigint_handler );
}
if( signal(SIGHUP,sighup_handler) < 0 ) {
EXCEPT( "signal(SIGHUP,0x%x)", sighup_handler );
}
if( signal(SIGPIPE,SIG_IGN) < 0 ) {
EXCEPT( "signal(SIGPIPE,SIG_IGN)" );
}
/*
if( signal(SIGALRM,abort) < 0 ) {
EXCEPT( "signal(SIGALRM,abort)" );
}
*/
ConnectionSock = init_connection_sock( "condor_startd", START_PORT );
UdpIn = init_udp_sock( "condor_startd", START_UDP_PORT );
UdpSock = udp_connect( CollectorHost, COLLECTOR_UDP_PORT );
if( signal(SIGCHLD,reaper) < 0 ) {
EXCEPT( "signal(SIGCHLD,reaper)" );
}
if( gethostname(ThisHost,sizeof ThisHost) < 0 ) {
EXCEPT( "gethostname" );
}
(void)sprintf( XSockName, "%s:0", ThisHost );
get_k_vars(); /* prepare to read kernel's process table */
LastTimeout = (int)time( (time_t *)0 );
timer.tv_usec = 0;
change_states( NO_JOB );
timeout();
FD_ZERO( &readfds );
for(;;) {
FD_SET( ConnectionSock, &readfds );
FD_SET( UdpIn, &readfds );
timer.tv_sec = PollingFrequency -
( (int)time((time_t *)0) - LastTimeout );
if( timer.tv_sec < 0 ) {
timer.tv_sec = 0;
}
count = select(FD_SETSIZE, (int *)&readfds, (int *)0, (int *)0,
(struct timeval *)&timer );
/*
** count = select(FD_SETSIZE, &readfds, 0, 0, 0 );
*/
if( count < 0 ) {
if( errno == EINTR ) {
continue;
} else {
EXCEPT( "select(FD_SETSIZE,0%o,0,0,%d sec)",
readfds, timer.tv_sec );
}
}
(void)sigblock( sigmask(SIGCHLD) ); /* Block out SIGCHLD */
if( count == 0 ) {
timeout();
}
if( FD_ISSET(ConnectionSock,&readfds) ) {
accept_connection();
}
if( FD_ISSET(UdpIn,&readfds) ) {
accept_datagram();
}
(void)sigsetmask( 0 ); /* Allow SIGCHLD */
}
}
accept_connection()
{
struct sockaddr_in from;
int len;
int fd;
XDR xdr, *xdrs, *xdr_Init();
len = sizeof from;
bzero( (char *)&from, sizeof from );
fd = accept( ConnectionSock, (struct sockaddr *)&from, &len );
if( fd < 0 && errno != EINTR ) {
EXCEPT( "accept" );
}
if( fd >= 0 ) {
xdrs = xdr_Init( &fd, &xdr );
do_command( xdrs, &from );
xdr_destroy( xdrs );
(void)close( fd );
}
}
accept_datagram()
{
XDR xdr, *xdrs, *xdr_Udp_Init();
int cmd;
xdrs = xdr_Udp_Init( &UdpIn, &xdr );
do_command( xdrs, &From );
xdr_destroy( xdrs );
}
init_connection_sock( service, port )
char *service;
int port;
{
struct sockaddr_in sin;
struct servent *servp;
int sock;
bzero( (char *)&sin, sizeof sin );
servp = getservbyname(service, "tcp");
if( servp ) {
sin.sin_port = htons( (u_short)servp->s_port );
} else {
sin.sin_port = htons( (u_short)port );
}
if( (sock=socket(AF_INET,SOCK_STREAM,0)) < 0 ) {
EXCEPT( "socket" );
}
if( setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(caddr_t *)&On,sizeof(On))< 0) {
EXCEPT( "setsockopt" );
}
#ifdef vax
if( setsockopt(sock,SOL_SOCKET,SO_LINGER,&linger,sizeof(linger)) < 0 ) {
EXCEPT( "setsockopt" );
}
#endif vax
if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
if( errno == EADDRINUSE ) {
EXCEPT( "CONDOR_STARTD ALREADY RUNNING" );
} else {
EXCEPT( "bind" );
}
}
if( listen(sock,5) < 0 ) {
EXCEPT( "listen" );
}
return sock;
}
reaper()
{
int pid;
union wait status;
struct rusage rusage;
while( (pid = wait3(&status,WNOHANG|WUNTRACED,&rusage)) > 0 ) {
if( WIFSTOPPED(status) ) {
dprintf( D_ALWAYS, "Starter %d has stopped\n", pid );
return;
}
if( WIFSIGNALED(status) ) {
dprintf( D_ALWAYS, "Starter %d died on signal %d\n",
pid, status.w_termsig );
} else {
dprintf( D_ALWAYS, "Starter %d exited with status %d\n",
pid, status.w_retcode );
}
job_dies();
}
}
/*
** Somebody has connected to our socket with a request. Read the request
** and handle it.
*/
do_command( xdrs, from )
XDR *xdrs;
struct sockaddr_in *from;
{
int cmd;
/* Read the request */
xdrs->x_op = XDR_DECODE;
if( !xdr_int(xdrs,&cmd) ) {
dprintf( D_ALWAYS, "Can't read command\n" );
return;
}
switch( cmd ) {
case START_FRGN_JOB: /* Request from foreign shadow to start a job */
start_job_request( xdrs, from );
break;
case CKPT_FRGN_JOB:
vacate_order();
break;
case KILL_FRGN_JOB:
kill_job( OK );
break;
case X_EVENT_NOTIFICATION:
x_event();
break;
default:
EXCEPT( "Got unknown command (%d)\n", cmd );
}
}
SetSyscalls(){}
init_params()
{
char *pval;
char *tmp;
Log = param( "LOG" );
if( Log == NULL ) {
EXCEPT( "No log directory specified in config file\n" );
}
Execute = param( "EXECUTE" );
if( Execute == NULL ) {
EXCEPT( "No Execute file specified in config file\n" );
}
Starter = param( "STARTER" );
if( Starter == NULL ) {
EXCEPT( "No Starter file specified in config file\n" );
}
CollectorHost = param( "COLLECTOR_HOST" );
if( CollectorHost == NULL ) {
EXCEPT( "No Collector host specified in config file\n" );
}
tmp = param( "POLLING_FREQUENCY" );
if( tmp == NULL ) {
PollingFrequency = 30;
} else {
PollingFrequency = atoi( tmp );
}
tmp = param( "POLLS_PER_UPDATE" );
if( tmp == NULL ) {
PollsPerUpdate = 4;
} else {
PollsPerUpdate = atoi( tmp );
}
if( param("STARTD_DEBUG") == NULL ) {
EXCEPT( "STARTD_DEBUG not defined in config file\n" );
}
Foreground = boolean( "STARTD_DEBUG", "Foreground" );
if( (CondorAdministrator = param("CONDOR_ADMIN")) == NULL ) {
EXCEPT( "CONDOR_ADMIN not specified in config file" );
}
pval = param("MEMORY");
if( pval != NULL ) {
Memory = atoi( pval );
}
if( Memory <= 0 || Memory >= 500 ) {
Memory = DEFAULT_MEMORY;
}
if( (Spool = param("SPOOL")) == NULL ) {
EXCEPT( "SPOOL not specified in config file" );
}
}
sigint_handler()
{
dprintf( D_ALWAYS, "Killed by SIGINT\n" );
exit( 0 );
}
sighup_handler()
{
dprintf( D_ALWAYS, "Re reading config file\n" );
free_context( MachineContext );
MachineContext = create_context();
config( MyName, MachineContext );
init_params();
}
cleanup_execute_dir()
{
char *execute, *rindex();
char buf[ 1024 ];
execute = rindex(Execute, '/');
if( execute == NULL ) {
execute = Execute;
} else {
execute++;
}
if( strcmp("execute", execute) != 0 ) {
EXCEPT("EXECUTE parameter (%s) must end with 'execute'.\n", Execute);
}
/* Take this out temporarily so we can get a core of the starter...
(void)sprintf(buf, "rm -f %s/*", Execute);
*/
(void)sprintf(buf, "rm -f %s/condor_exec*", Execute);
(void)system(buf);
}
init_udp_sock( service, port )
char *service;
int port;
{
struct sockaddr_in sin;
struct servent *servp;
int sock;
bzero( (char *)&sin, sizeof sin );
servp = getservbyname(service, "tcp");
if( servp ) {
sin.sin_port = htons( (u_short)servp->s_port );
} else {
sin.sin_port = htons( (u_short)port );
}
if( (sock=socket(AF_INET,SOCK_DGRAM,0)) < 0 ) {
EXCEPT( "socket" );
}
if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
if( errno == EADDRINUSE ) {
EXCEPT( "CONDOR_COLLECTOR ALREADY RUNNING" );
} else {
EXCEPT( "bind" );
}
}
return sock;
}