/* * Copyright (c) 1998 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ /********** test.c **********/ #include #include #include #include #include #include #include #include #include #include #include "nefu.h" #include "ll.h" #include "ttable.h" int nefu_test_maxwait = -1; char *test_errstr[] = { "test_errstr: no error!", "test not found in table", #define TEST_NOT_FOUND 1 "bad port", #define TEST_BAD_PORT 2 "test doesn't have a port", #define TEST_NO_PORT 3 "test name can't be NULL", #define TEST_NULL_NAME 4 "ping can't be redefined", #define TEST_PING_ONCE 4 NULL }; void test_argv( struct test *t, char **argv ) { int len; if ( argv == NULL ) { return; } len = strlen( t->t_full_name ) + 1; for ( t->t_argc = 0; t->t_argc < TEST_MAX_ARGS + 1; t->t_argc++ ) { if ( argv[ t->t_argc ] != NULL ) { /* build t->t_argv */ if (( t->t_argv[ t->t_argc ] = strdup( argv[ t->t_argc ] )) == NULL ) { perror( "strdup" ); exit( 1 ); } /* create t->t_full_name */ len += ( strlen( argv[ t->t_argc ]) + 1 ); if (( t->t_full_name = (char*)realloc( t->t_full_name, len )) == NULL ) { perror( "realloc" ); exit( 1 ); } sprintf( t->t_full_name, "%s %s", t->t_full_name, argv[ t->t_argc ]); } else { /* we're done */ t->t_argv[ t->t_argc ] = NULL; break; } } } void test_rcodes( struct test *t, struct rcode *r ) { int len; for ( ; r != NULL; r = r->r_next ) { ll_insert( &t->t_rcodes, r->r_code, r ); if ( t->t_rlist == NULL ) { if (( t->t_rlist = strdup( r->r_code )) == NULL ) { perror( "strdup" ); exit( 1 ); } } else { len = strlen( t->t_rlist ) + strlen( r->r_code ) + 2; if (( t->t_rlist = (char*)realloc( t->t_rlist, len )) == NULL ) { perror( "realloc" ); exit( 1 ); } sprintf( t->t_rlist, "%s,%s", t->t_rlist, r->r_code ); } } } /* args: * m must be valid machine * r NULL to default to machine's rlist, valid otherwise * yy_name test name as given by yacc. it must be in the format of * name[:port] where name is the test name and the port is a * colon followed by an integer. Note that T_DEFAULT and * T_SHELL are special names. * yy_line 0 is implicit test for machine, > 0 line from yacc * argv arg vector for the test */ char * test( struct machine *m, struct rcode *r, char *yy_name, int yy_lineno, char **argv ) { struct test *t = NULL; struct testtable *tt; int len; char *name; char *port; char *err; if ( yy_name == NULL ) { return( test_errstr[ TEST_NULL_NAME ]); } if (( name = strdup( yy_name )) == NULL ) { perror( "strdup" ); exit( 1 ); } if (( port = strchr( name, ':' )) != NULL ) { *port = '\0'; port++; } if ( strcasecmp( name, T_DEFAULT ) == 0 ) { /* ping never has a port */ if ( port != NULL ) { return( test_errstr[ TEST_NO_PORT ]); } if (( t = m->m_test ) != NULL ) { /* modify ping explicitly once */ if ( t->t_line != 0 ) { return( test_errstr[ TEST_PING_ONCE ]); } t->t_line = yy_lineno; /* default test may already have default rcodes */ if ( t->t_rlist != NULL ) { free( t->t_rlist ); t->t_rlist = NULL; t->t_rcodes = NULL; } test_rcodes( t, r ); test_argv( t, argv ); if (( err = init_ping( t )) != NULL ) { return( err ); } return( NULL ); } } if ( strcasecmp( name, T_SHELL ) == 0 ) { if ( port != NULL ) { return( test_errstr[ TEST_NO_PORT ]); } } /* find entry in nefu's test table */ for ( tt = testtable; tt->tt_name != NULL; tt++ ) { if ( strcasecmp( tt->tt_name, name ) == 0 ) { break; } } if ( tt->tt_name == NULL ) { /* we didn't find that test */ return( test_errstr[ TEST_NOT_FOUND ]); } /* create a new test */ if (( t = (struct test*)malloc( sizeof( struct test ))) == NULL ) { perror( "malloc" ); exit( 1 ); } memset( t, 0, sizeof( struct test )); if ( m->m_dns_status == 0 ) { t->t_status = T_UP; } else { t->t_status = T_NO_DNS; if ( gettimeofday( &t->t_time_down, NULL ) != 0 ) { perror( "gettimeofday" ); exit( 1 ); } } t->t_machine = m; t->t_name = tt->tt_name; t->t_test = tt->tt_func; t->t_sin.sin_family = AF_INET; t->t_sin.sin_addr.s_addr = t->t_machine->m_sin.sin_addr.s_addr; len = ( strlen( t->t_name ) + 1 ); if (( t->t_full_name = (char*)malloc( len )) == NULL ) { perror( "malloc" ); exit( 1 ); } sprintf( t->t_full_name, "%s", t->t_name ); if ( port != NULL ) { if (( t->t_sin.sin_port = htons( atoi( port ))) == 0 ) { return( test_errstr[ TEST_BAD_PORT ]); } len += ( strlen( port ) + 1 ); if (( t->t_full_name = (char*)realloc( t->t_full_name, len )) == NULL ) { perror( "realloc" ); exit( 1 ); } sprintf( t->t_full_name, "%s:%s", t->t_full_name, port ); } else { t->t_sin.sin_port = htons( tt->tt_port ); } free( name ); /* insert test */ if ( m->m_test == NULL ) { m->m_test = t; } else { t->t_parent = m->m_test; t->t_peer = m->m_test->t_child; if ( t->t_peer != NULL ) { t->t_peer->t_prev = t; } m->m_test->t_child = t; } test_rcodes( t, r ); test_argv( t, argv ); return((*tt->tt_init)( t )); }