/* ******************************************************************************* * Copyright (c) 1997 Martin Poole * ******************************************************************************* ** ** WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! ** ** Any changes to be made to this file should first be checked with ** mplib1 source control for library integrity. ** ** mplib1 source control can be reached at mplib1@quatermass.co.uk ** * * $Source: /home/cvs/cvsroot/onelan/onelan/src/mplib1/util/w_ctrl.c,v $ * $Author: mpoole $ * $Date: 2002/10/07 09:37:30 $ * $Revision: 1.2 $ * Purpose : * ******************************************************************************* * * Change History * * $Log: w_ctrl.c,v $ * Revision 1.2 2002/10/07 09:37:30 mpoole * Initial checkin of mplib1-3.1.0 * * Revision 1.1 2002/10/07 09:37:09 mpoole * Initial checkin of mplib1-3.1.0 * * ******************************************************************************* */ #ident "$Header: /home/cvs/cvsroot/onelan/onelan/src/mplib1/util/w_ctrl.c,v 1.2 2002/10/07 09:37:30 mpoole Exp $" /* ------------------------------------------------------------------ Include files ------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "watchdog.h" #include "watch_lock.h" /* ------------------------------------------------------------------ defines ------------------------------------------------------------------ */ static struct match_token internal_commands[]= { { 1, "^quit" }, { 1, "^QUIT" }, { 2, "^look" }, { 2, "^LOOK" }, { 3, "^help" }, { 3, "^HELP" }, { 0, NULL } }; static int verbose=0; /* ------------------------------------------------------------------ Code starts here ------------------------------------------------------------------ */ static void usage ( const char *progname, const char *errstr ) { if (errstr) fprintf( stderr, "Error: %s\n", errstr ); fprintf(stderr, "\nUsage: %s [ -f filename ] [ -v ] commands ...\n", progname ); exit(1); return; } static int set_output_files( void ) { char *cp1,*cp2; cp1 = eval_config_default( "CTRL_STDOUT", NULL ); cp2 = eval_config_default( "CTRL_STDERR", NULL ); restart_these_files( NULL, cp1, cp2 ); return(0); } static struct watchdog_ctrl_msg * Send_And_Get( struct watchdog_ctrl_msg *cmp, struct bpo_Q *myq ) { struct watchdog_ctrl_msg *rv; rv = bpo_send_and_get( WATCH_CTRL_Q, &cmp->ctrl_msg, myq ); return(rv); } static struct watchdog_ctrl_msg * do_this_ctrl_msg( struct watchdog_ctrl_msg *cmp, struct bpo_Q *myq ) { cmp = Send_And_Get( cmp, myq ); if(cmp) { fprintf(stderr, "Reply: %s\n", cmp->rep_buf ); } else { fprintf(stderr, "Nothing on Q to read\n" ); } return(cmp); } static int interactive_loop( struct watchdog_ctrl_msg *rcmp, struct bpo_Q *myq ) { int loop=1; while ( loop==1 && rcmp && fgetline( stdin, rcmp->comm_buf, sizeof(rcmp->comm_buf) )==0 ) { switch( match_a_string( rcmp->comm_buf, internal_commands, NULL )) { case 1 : /* quit */ loop = 0; break; case 2 : /* look */ /* print_monitor_resource( stdout );*/ break; case 3 : /* help */ printf("Help unavailable at the moment\n" ); break; default : /* unknown, pass to watchdog */ rcmp = do_this_ctrl_msg( rcmp, myq ); } } return(1); } static int use_ctl_file( char *ctl_file, struct watchdog_ctrl_msg *rcmp, struct bpo_Q *myq ) { FILE *fh; int rv=1; if ( (fh=fopen(ctl_file,"r")) ) { while(rcmp && fgetline2( fh, rcmp->comm_buf, CTL_BUF_SZ )==0) { fprintf( stderr, "Command: %s\n", rcmp->comm_buf ); rcmp = do_this_ctrl_msg( rcmp, myq ); }; fclose(fh); if (rcmp==NULL) rv= -1; } return(rv); } static int check_watchdog( void ) { /* The watchdog has stored its pid in the lock file, In addition, it should be updating the timestamp on the lock file whilst it is running. If the file is not there, watchdog is not there. If the pid is dead, watchog is not there. If the timestamp is >60s ago, watchdog is locked */ struct stat wstat; time_t now; FILE *fp; char tbuf[40]; pid_t wpid; int rv=-1; const char *lock_file; lock_file = get_lock_name(); if (stat( lock_file, &wstat )==0) { /* ok, now open and read a line */ fp = fopen( lock_file, "r" ); if (fp) { if (fgetline(fp, tbuf, 40)==0) { wpid = atol( tbuf ); if (wpid) { if (is_pid_dead(wpid)) { if (verbose) fprintf( stderr, "watchdog process is dead = %d\n", errno ); rv=errno; }else { (void)time(&now); if ( (now-60) > wstat.st_mtime ) { rv = ETXTBSY; fprintf( stderr, "watchdog appears to have locked\n" ); }else rv=0; } }else { rv= errno; if (verbose) fprintf( stderr, "Unable to determine pid <%s> = %d\n", tbuf, errno ); } }else { rv = errno; fprintf( stderr, "Unable to read line from lock file <%s> = %d\n", lock_file, errno ); } fclose(fp); }else { rv = errno; if (verbose) fprintf( stderr, "Unable to open lock file <%s> = %d\n", lock_file, errno ); } }else { rv = errno; if (verbose) fprintf(stderr, "watchdog lock file does not exist <%s> = %d\n", lock_file, errno ); } return(rv); } int main ( int argc, char *argv[] ) { int optc,rv=0; int cfg_read=0; char *cp; char config_name[200]; void *myq; struct watchdog_ctrl_msg *cmp,*rcmp; int loop=0; void *comms_hint; char *ctl_file=NULL; int set_outfiles=0,opt_C=0; while ((optc = getopt(argc, argv, "Colvc:f:")) != EOF) switch (optc) { case 'f': strcpy( config_name, optarg ); read_config_file( optarg ); cfg_read=1; break; case 'c': ctl_file=optarg; break; case 'o': set_outfiles=1; break; case 'v': verbose = 1; break; case 'l': loop = 1; break; case 'C': opt_C=1; break; default: usage( argv[0], "Invalid argument supplied" ); break; } if (!cfg_read) { cp = eval_config_default( NULL, "$HOME/config/watchdog.cfg" ); strcpy( config_name, cp ); if (!read_config_file( config_name )) { usage( argv[0], "Config file not found\n" ); } } if (optind >= argc && loop==0 && ctl_file==NULL && opt_C==0) { fprintf(stderr,"No arguments supplied\n" ); return(0); } if (set_outfiles) set_output_files( ); if (getenv("PROGRAM_NAME")==NULL) Set_My_Proc_Details( NULL, mpbasename(argv[0]), NULL, NULL, 0600, 0 ); /* Now we check how the watchdog is doing without attaching */ rv = check_watchdog(); if (opt_C || rv) exit(rv); if (get_config_flag("NO_SHARED_MEMORY")==0) { comms_hint = comms_shm_attach( eval_config_default( "SHM_CONFIG", "$HOME/config/shm.cfg" ), SODB_READ_CONFIG ); if (comms_hint==NULL) usage( argv[0], "Unable to attach to shared memory\n" ); cmp = shalloc( comms_hint, sizeof(struct watchdog_ctrl_msg) ); myq = mpCreateQ( comms_hint, NULL, 0, Q_SOLE_READER, Q_NM_PIPE ); if (cmp && myq) { bpo_Init_Node( &cmp->ctrl_msg.Q_Node, NULL, cmp ); cmp->rep_buf[0]='\0'; if (ctl_file) { rv = use_ctl_file( ctl_file, cmp, myq ); }else if (optindcomm_buf, argv[optind++] ); while (optindcomm_buf, " " ); strcat( cmp->comm_buf, argv[optind++] ); }; if (verbose) fprintf( stderr, "Command: <%s>\n", cmp->comm_buf ); rcmp = do_this_ctrl_msg( cmp, myq ); rv = (rcmp==NULL)? -1:0; }else if (loop) { interactive_loop( cmp, myq ); rv = 0; } } Deregister_Process_Details( comms_hint ); comms_shm_detach( ); }else { fprintf( stderr, "Unable to communicate with watchdog\n" ); rv= -1; } return(rv); } /* -- End of File -- */