/* ******************************************************************************* * 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$ * $Author$ * $Date$ * $Revision$ * Purpose : Generic Program Watchdog * ******************************************************************************* * * Change History * * $Log$ * ******************************************************************************* */ #ident "$Header$" /* ------------------------------------------------------------------ Include files ------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "watchdog.h" #include #include /* ------------------------------------------------------------------ structures / defines ------------------------------------------------------------------ */ struct pl_search { struct level_hdr *level; void (*pfunc)(struct program_hdr *, void *param); void *param; }; /* ------------------------------------------------------------------ Static Data ------------------------------------------------------------------ */ static GDBM_FILE job_file; static struct gdbm_help job_file_help = { "JOB_FILE", "$HOME/gdbm_files/watchdog/job_file", "JOB_BLOCKSIZE", "JOB_CACHESIZE", NULL, NULL, NULL, &job_file, NULL }; static dl_List_t program_list; static dl_List_t tag_list; static int done_init=0; /* ------------------------------------------------------------------ Code starts here ------------------------------------------------------------------ */ static void check_init( void ) { if (done_init==0) { dl_Init_List( &program_list, 0 ); dl_Init_List( &tag_list, 0 ); done_init=1; } return; } static int track_item_on_list( dl_List_t *lp, void *the_item ) { dl_Node_t *np; int rv=0; np = malloc( NODE_SIZE ); if (np) { dl_Init_Node( np, NULL, the_item ); dl_Add_Tail( lp, np ); rv=1; } return(rv); } void free_program( struct program_hdr *pptr ) { if(pptr) { dl_Remove_Node( &pptr->prg_Node ); free( pptr ); } return; } void free_level( struct level_hdr *lptr ) { if (lptr) { dl_Remove_Node( &lptr->lvl_hdr ); free( lptr ); } return; } static void free_all_items( void ) { dl_Walk_List( &program_list, (dl_Walk_List_t)free_program, NULL ); dl_Walk_List( &tag_list, (dl_Walk_List_t)free_level, NULL ); return; } int close_job_file( void ) { int rv; rv = gdbm_db_close( &job_file_help ); free_all_items(); return(rv); } int open_job_file( void ) { int rv; check_init(); close_job_file(); rv = gdbm_db_open( &job_file_help, 0 ); return(rv); } size_t gen_level_line( char *obuf, struct level_hdr *lptr ) { sprintf( obuf, "LEVEL %s LOWER %d UPPER %d ACTIVE %s", &lptr->key[1], lptr->lower_level, lptr->upper_level, (const char *)((lptr->active)? "TRUE" : "FALSE") ); return(strlen(obuf)+1); } int print_lvl_hdr( struct level_hdr *lptr, FILE *fp ) { char obuf[2000]; size_t olen; int rv=0; olen = gen_level_line( obuf, lptr ); fprintf( fp, "%s\n", obuf ); return(rv); } int delete_lvl_hdr( struct level_hdr *lptr ) { int rv; rv = delete_some_record( job_file, "%s", lptr->key ); return(rv); } int save_lvl_hdr( struct level_hdr *lptr ) { char obuf[2000]; size_t olen; int rv; olen = gen_level_line( obuf, lptr ); /*fprintf(stderr, "saving: %s %s\n", lptr->key, obuf );*/ rv = store_some_record( job_file, obuf, olen, "%s", lptr->key ); return(rv); } static char * eos( char *buf ) { while(*buf) buf++; return(buf); } static char * sappend( char *buf, const char *fmt, ... ) { va_list ap; buf=eos(buf); va_start( ap, fmt ); vsprintf( buf, fmt, ap ); va_end (ap ); return(eos(buf)); } size_t gen_program_line( char *line, struct program_hdr *pptr ) { char *obuf=line; if (pptr->ptype==PRG_HDR_DAEMON) sprintf( obuf, "DAEMON %s", &pptr->key[1] ); else sprintf( obuf, "BATCH %s", &pptr->key[1] ); if (pptr->grp_name && *pptr->grp_name) obuf = sappend( obuf, " GROUP %s", pptr->grp_name ); obuf = sappend( obuf, " LEVEL %d", pptr->level ); if (pptr->exe_name && *pptr->exe_name) obuf = sappend( obuf, " EXE %s", pptr->exe_name ); if (pptr->pid_name && *pptr->pid_name) obuf = sappend( obuf, " PIDFILE %s", pptr->pid_name ); if (pptr->copies > 1) obuf = sappend( obuf, " COPIES %d", pptr->copies ); obuf = sappend( obuf, " ACTIVE %s", (pptr->active)? "TRUE" : "FALSE" ); obuf = sappend( obuf, " EXCLUSIVE %s", (pptr->exclusive)? "TRUE" : "FALSE" ); obuf = sappend( obuf, " PIDTRACK %s", (pptr->track_by_pid)? "TRUE" : "FALSE" ); if (pptr->err_name && *pptr->err_name) obuf = sappend( obuf, " STDERR %s", pptr->err_name ); if (pptr->out_name && *pptr->out_name) obuf = sappend( obuf, " STDOUT %s", pptr->out_name ); if (pptr->env_name && *pptr->env_name) obuf = sappend( obuf, " ENVIRONMENT %s", pptr->env_name ); if (pptr->startup > 0) obuf = sappend( obuf, " STARTUP %d", pptr->startup ); if (pptr->sp_limit > 0) obuf = sappend( obuf, " SPAWN_LIMIT %d", pptr->sp_limit ); if (pptr->sp_hold > 0) obuf = sappend( obuf, " SPAWN_HOLD %d", pptr->sp_hold ); if (pptr->sp_window > 0) obuf = sappend( obuf, " SPAWN_WINDOW %d", pptr->sp_window ); if (pptr->opt_name && *pptr->opt_name) obuf = sappend( obuf, " PARAMS %s", pptr->opt_name ); return(strlen(line)+1); } int print_prg_hdr( struct program_hdr *pptr, FILE *fp ) { char obuf[8000]; size_t olen; int rv=0; olen = gen_program_line( obuf, pptr ); fprintf( fp, "%s\n", obuf ); return(rv); } int save_prg_hdr( struct program_hdr *pptr ) { char obuf[8000]; size_t olen; int rv; olen = gen_program_line( obuf, pptr ); /*fprintf(stderr, "saving: %s %s\n", pptr->key, obuf );*/ rv = store_some_record( job_file, obuf, olen, "%s", pptr->key ); return(rv); } int delete_prg_hdr( struct program_hdr *pptr ) { int rv; rv = delete_some_record( job_file, "%s", pptr->key ); return(rv); } int add_this_level( const char *level_name, char *level_line, int db_save ) { int rv=0; struct level_hdr *lptr; size_t msize; if (level_name) lptr = dl_Find_Item_By_Name( &tag_list, level_name ); else lptr = NULL; if (lptr) { /* Remove this version and install the new one */ lptr->lower_level=0; lptr->upper_level=0; lptr->active=0; }else { msize = sizeof(struct level_hdr) + strlen(level_name); lptr = malloc( msize ); if (lptr) { memset( lptr, '\0', msize ); if (level_name) { lptr->key[0] = LVL_HDR_C; strcpy( &lptr->key[1], level_name ); } dl_Init_Node( &lptr->lvl_hdr, &lptr->key[1], lptr ); dl_Add_Head( &tag_list, &lptr->lvl_hdr ); } } /* Now parse this datum and transfer it to the pointers */ if (lptr) { parse_level_tag( lptr, level_line ); if (db_save) save_lvl_hdr( lptr ); rv = GDBM_IDUMP_KEEP_DATA; } return(rv); } int add_this_program( const char *prg_name, char *prg_line, int db_save, int ptype ) { int rv=0; struct program_hdr *pptr; size_t msize,olen; char obuf[8000]; char *new_data; if (prg_name) pptr = dl_Find_Item_By_Name( &program_list, prg_name ); else pptr = NULL; if (pptr==NULL) { msize = sizeof(struct program_hdr) + strlen(prg_name); pptr = malloc( msize ); if (pptr) { memset( pptr, '\0', msize ); if (prg_name) { if (ptype==PRG_HDR_DAEMON) pptr->key[0] = PRG_HDR_DAEMON_C; else if (ptype==PRG_HDR_BATCH) pptr->key[0] = PRG_HDR_BATCH_C; else pptr->key[0] = '_'; strcpy( &pptr->key[1], prg_name ); } pptr->copies=1; pptr->prg_name = &pptr->key[1]; if (ptype==0) ptype=PRG_HDR_BATCH; pptr->ptype = ptype; dl_Init_Node( &pptr->prg_Node, &pptr->key[1], pptr ); dl_Init_List( &pptr->running_pids, 0 ); dl_Init_List( &pptr->mem_bits, 0 ); dl_Add_Head( &program_list, &pptr->prg_Node ); } } /* Now parse this datum and transfer it to the pointers */ if (pptr) { parse_program_tag( pptr, prg_line ); if (db_save) save_prg_hdr( pptr ); if (dl_Any_In_List( &pptr->mem_bits )) { olen = gen_program_line( obuf, pptr ); new_data = strdup( obuf ); if(new_data) { dl_Free_List( &pptr->mem_bits, DL_FREE_NODES | DL_FREE_ITEMS ); add_this_program( prg_name, new_data, 0, pptr->ptype ); }else { /* try and save both for the time being */ track_item_on_list( &pptr->mem_bits, new_data ); rv = GDBM_IDUMP_KEEP_DATA; } }else { /* Must be a new item, save it on the list */ track_item_on_list( &pptr->mem_bits, prg_line ); rv = GDBM_IDUMP_KEEP_DATA; } } return(rv); } static int read_item( FILE *fp, char *key, char *p1 ) { int rv; /* fprintf(stderr,"read db: key <%s> data <%s>\n", key, p1 );*/ if (*key==PRG_HDR_DAEMON_C) { /* It's a program */ rv = add_this_program( key+1, p1, 0, PRG_HDR_DAEMON ); } else if (*key==PRG_HDR_BATCH_C) { /* It's a program */ rv = add_this_program( key+1, p1, 0, PRG_HDR_BATCH ); } else if (*key==LVL_HDR_C) { /* Level tag */ rv = add_this_level( key+1, p1, 0 ); }else { fprintfile( stderr, "Unknown key in control file %s\n", key ); rv=0; } return(rv); } int read_job_file( ) { free_all_items( ); /* needed ? */ gdbm_index_dump( stderr, &job_file_help, GDBM_IDUMP_SORT|GDBM_IDUMP_NOCASE|GDBM_IDUMP_DATA, (int (*)(FILE *,char *,void *))read_item ); return(0); } int dump_jobs( FILE *fp ) { dl_Walk_List( &tag_list, (dl_Walk_List_t)print_lvl_hdr, fp ); dl_Walk_List( &program_list, (dl_Walk_List_t)print_prg_hdr, fp ); return(0); } struct program_hdr * find_program_hdr( const char *name ) { struct program_hdr *pptr; pptr=dl_Find_Item_By_Name( &program_list, name ); return(pptr); } struct level_hdr * find_level_hdr( const char *name ) { struct level_hdr *lptr; lptr=dl_Find_Item_By_Name( &tag_list, name ); return(lptr); } int level_applies_to_program( struct level_hdr *lptr, struct program_hdr *pptr ) { return ( lptr->lower_level && lptr->upper_level && pptr->level && lptr->lower_level <= pptr->level && lptr->upper_level >= pptr->level ); } static void level_apply( struct level_hdr *lptr, struct program_hdr *pptr ) { if ( lptr->active && lptr->lower_level && lptr->upper_level && pptr->level && lptr->lower_level <= pptr->level && lptr->upper_level >= pptr->level ) pptr->lvl_exclude++; return; } int apply_levels_to_program( struct program_hdr *pptr ) { pptr->lvl_exclude=0; dl_Walk_List( &tag_list, (dl_Walk_List_t)level_apply, pptr ); return( pptr->lvl_exclude ); } int set_all_program_levels( ) { dl_Walk_List( &program_list, (dl_Walk_List_t)apply_levels_to_program, NULL ); return(0); } int walk_all_programs( void (*pfunc)(struct program_hdr *, void *param), void *param ) { dl_Walk_List( &program_list, (dl_Walk_List_t)pfunc, param ); return(0); } int walk_all_levels( void (*pfunc)(struct level_hdr *, void *param), void *param ) { dl_Walk_List( &tag_list, (dl_Walk_List_t)pfunc, param ); return(0); } static void check_for_level( struct program_hdr *pptr, struct pl_search *plsp ) { if (level_applies_to_program( plsp->level, pptr )) (*plsp->pfunc)( pptr, plsp->param ); return; } int walk_all_programs_in_level( struct level_hdr *lptr, void (*pfunc)(struct program_hdr *, void *param), void *param ) { struct pl_search pls; pls.level = lptr; pls.pfunc = pfunc; pls.param = param; dl_Walk_List( &program_list, (dl_Walk_List_t)check_for_level, &pls ); return(0); } /* -- End of File -- */