void ach_die(void) { /* notify failure if not our parent */ if( getppid() != ach_pid_notify ) ach_notify(ACH_SIG_FAIL); exit(EXIT_FAILURE); }
int main( int argc, char **argv ) { /* Check if we're running under achcop */ if( getenv("ACHCOP") ) { ach_pid_notify = getppid(); } int c; while( (c = getopt( argc, argv, "zlnh?V")) != -1 ) { switch(c) { case 'v': ach_verbosity ++; break; case 'l': opt_last = 1; break; case 'n': opt_last = 0; break; case 'z': opt_gzip = 1; break; /* case 'f': */ /* opt_freq = atof(optarg); */ /* break; */ case 'V': /* version */ ach_print_version("achpipe.bin"); exit(EXIT_SUCCESS); case '?': case 'h': case 'H': puts( "Usage: achlog [OPTIONS] channels...\n" "Log ach channels to files" "\n" "Options:\n" " -?, Show help\n" " -z, Filter output through gzip\n" "\n" "Examples:\n" " achlog foo bar Log channels foo and bar\n" "\n" "Report bugs to <*****@*****.**>" ); exit(EXIT_SUCCESS); default: posarg(optarg); } } while( optind < argc ) { posarg(argv[optind++]); } if( 0 == n_log ) ACH_DIE("No channels to log\n"); /* Block Signals */ /* Have to block these before forking so ctrl-C doesn't kill the * gzip */ int sigs[] = {SIGTERM, SIGINT, 0}; ach_sig_block_dummy( sigs ); /* Open Channels */ size_t i; for( i = 0; i < n_log; i ++ ) { ach_status_t r = ach_open(&log_desc[i].chan, log_desc[i].name, NULL); if( ACH_OK != r ) { ACH_DIE( "Could not open channel %s: %s\n", log_desc[i].name, ach_result_to_string(r) ); } /* Open log file */ if( opt_gzip ) { log_desc[i].fout = filter( "gzip -c", log_desc[i].name, ".gz" ); } else { log_desc[i].fout = fopen(log_desc[i].name, "w"); } if( NULL == log_desc[i].fout ) { ACH_DIE( "Could not open log file for %s: %s\n", log_desc[i].name, strerror(errno) ); } } /* get some data */ if( clock_gettime(ACH_DEFAULT_CLOCK, &now_ach ) || clock_gettime(CLOCK_REALTIME, &now_real ) ) { ACH_DIE( "Could not get time: %s\n", strerror(errno) ); } if( gethostname( host, sizeof(host) ) ) { ACH_LOG(LOG_ERR, "Could not get host name: %s\n", strerror(errno)); } host[sizeof(host)-1] = '\0'; passwd = getpwuid(getuid()); if( passwd ) { strtok(passwd->pw_gecos, ","); } now_real_str = ctime( &now_real.tv_sec ); /* Create Workers */ pthread_t thread[n_log]; for( i = 0; i < n_log; i ++ ) { int r = pthread_create( thread+i, NULL, worker, (void*)(log_desc+i) ); if( r ) ACH_DIE( "Couldn't start worker thread: %s\n", strerror(r) ); } ach_notify(ACH_SIG_OK); /* Wait for Signal */ ach_sig_wait( sigs ); /* Cancel workers */ ach_cancel_attr_t cattr; ach_cancel_attr_init( &cattr ); cattr.async_unsafe = 1; for( i = 0; i < n_log; i ++ ) { ach_cancel( &log_desc[i].chan, &cattr ); } /* Join worker threads */ for( i = 0; i < n_log; i ++ ) { int r = pthread_join( thread[i], NULL ); if( r ) ACH_DIE( "Couldn't join worker thread: %s\n", strerror(r) ); if( opt_gzip ) { if( pclose(log_desc[i].fout) < 0 ) { ACH_LOG( LOG_ERR, "Could not pclose output for %s: %s\n", log_desc[i].name, strerror(errno) ); } } else { fclose(log_desc[i].fout); } } return 0; }