head 3.0; access oasisa; symbols ; locks ; strict; comment @ * @; 3.0 date 99.05.12.10.11.32; author bobh; state Exp; branches ; next 2.9; 2.9 date 98.08.24.13.46.00; author bobh; state Exp; branches ; next ; desc @Program to send commands to OASIS controller via packet radio @ 3.0 log @Added tstring, misc changes @ text @/****************************************************************************/ /* Copyright 1992 MBARI */ /****************************************************************************/ /* $Header: sendoasis.c,v 2.9 98/08/24 13:46:00 bobh Exp $ */ /* Summary : Program to send commands to OASIS controller and get response */ /* Filename : sendoasis.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 2.9 $ */ /* Created : 05/15/98 from getoasis.c */ /****************************************************************************/ /* Modification History: */ /* 15may98 rah - created from getoasis.c */ /* $Log: sendoasis.c,v $ * Revision 2.9 98/08/24 13:46:00 13:46:00 bobh (Bob Herlien) * Archiving sources after M2/M3 & Eqpac deployments of 1998 * */ /****************************************************************************/ #include /* Standard I/O */ #include /* For exit() */ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* For timeout */ #include /* For terminal I/O stuff */ #include /* For open() stuff */ #include /* For signal() */ #include /* For toupper() */ #include /* For strchr() */ #include "decode.h" /* For LogStruct */ #define TNC_DEV "tnc" /* Default radio TNC device file */ #define BUFSIZE 1023 /* Size of line buffer */ #define TNC_ADDR "mbari-3" /* Dflt TNC to connect to */ #define OPROMPT "OASIS>" /* OASIS prompt */ #define CAN_NAME "m1" /* Can name */ #define ARG_ERR 1 /* Bad command line arg exit() code */ #define PORT_ERR 2 /* Serial port error exit() code */ #define CONNECT_ERR 3 /* Can't connect exit() code */ #define DOWNLOAD_ERR 4 /* Download error exit() code */ #define ABORT_ERR 5 /* Aborted exit() code */ #define TIMEOUT_ERR 6 /* Timeout */ /********************************/ /* External Functions */ /********************************/ /* From port.c */ Extern MBool set_baud( struct termio *tp, Int baud ); Extern Int get_port( char *name, Int mode, struct termio *setup, struct termio *save ); Extern Status release_port( char *name, Int fd, struct termio *parms ); /********************************/ /* External Data */ /********************************/ Extern char *optarg; /* Option argument from getopt() */ Extern Int optind; /* Option index from getopt() */ Extern Int opterr; /* getopt() error flag */ /********************************/ /* Module Local Data */ /********************************/ MLocal char *tncfile = TNC_DEV; /* Radio TNC device file */ MLocal char *tncaddr = TNC_ADDR; /* TNC address to connect to */ MLocal time_t timeout = 660; /* 11 minute timeout by default */ MLocal time_t prompt_tmout = 10; /* 60 seconds for prompt */ MLocal Int32 tfd = ERROR; /* TNC file descriptor */ MLocal char *cmdfile = NULL; /* Command file name */ MLocal MBool echo = FALSE; /* TRUE to echo tnc reads to stdout */ MLocal MBool aborted = FALSE; /* Set from signal handler */ MLocal char rbuf[BUFSIZE+1]; /* Read line buffer */ MLocal Nat32 rcnt = 0; /* # chars in rbuf */ MLocal LogStruct logs; /* Which records have been read */ MLocal struct termio tnc_term = /* Termio characteristics for TNC */ { IGNPAR, /* c_iflag */ 0, /* c_oflag */ B9600 | CS8 | CREAD | CLOCAL, /* c_cflag */ NOFLSH, /* c_lflag */ 0, /* c_line, HP has no line disciplines*/ {0, 0, 0, 0, 0, 10, 0, 0} /* control chars (1 second timeout) */ }; MLocal struct termio tnc_save; /* Place to save terminal charac. */ MLocal char *setup_tnc[] = { "NO OFF\r", "EC OFF\r", "RET 15\r", "M OFF\r" }; MLocal char *restore_tnc[] = { "EC ON\r" }; /********************************/ /* Forward Declarations */ /********************************/ MBool process_command_line ( Int argc, char **argv ); Void use_msg( char *s ); Status connect_tnc( Void ); Status disconnect_tnc( Void ); Status write_tnc( char *s ); Status send_tnc_cmds( char *cmds[], Int num ); Status sendUsrCmds( Void ); Void quit( Int sig ); /************************************************************************/ /* Function : main */ /* Purpose : Main routine */ /* Inputs : argc, argv */ /* Outputs : none */ /************************************************************************/ Void main( Int argc, char **argv ) { Int rtn; /* exit() code */ printf("OASIS command program $Revision: 2.9 $\n"); if ( !process_command_line(argc, argv) ) { use_msg(argv[0]); exit( ARG_ERR ); } signal(SIGTERM, quit); /* Catch terminate signals */ signal(SIGHUP, quit); signal(SIGINT, quit); signal(SIGQUIT, quit); if ( (tfd = get_port(tncfile, O_RDWR, &tnc_term, &tnc_save)) == ERROR ) { printf( "Couln't acquire serial port %s\n", tncfile ); exit( PORT_ERR ); } printf("Acquired serial port %s\n", tncfile); if ( send_tnc_cmds(setup_tnc, sizeof(setup_tnc)/sizeof(char *)) == ERROR ) printf( "Failed to setup TNC commands\n" ); if ( connect_tnc() == OK ) { rtn = wait_for_prompt(); /* Look for initial prompt*/ if ( rtn == OK ) rtn = sendUsrCmds(); write_tnc( "quit\r" ); sleep( 3 ); } else { printf( "Couldn't establish radio communication\n" ); rtn = CONNECT_ERR; } disconnect_tnc(); send_tnc_cmds( restore_tnc, sizeof(restore_tnc)/sizeof(char *) ); sleep( 1 ); printf("\n"); if ( release_port(tncfile, tfd, &tnc_save) == ERROR ) printf( "Error in releasing serial port %s\n", tncfile ); exit( aborted ? ABORT_ERR : rtn ); } /* main() */ /************************************************************************/ /* Function : use_msg */ /* Purpose : Print Usage Message */ /* Inputs : Name of program */ /* Outputs : None */ /************************************************************************/ Void use_msg( char *s ) { fprintf( stderr, "Usage: %s [-a tnc_address] [-b baud] [-f cmdFile] [-p port]", s ); fprintf( stderr, " [-t timeout]\n"); } /* use_msg() */ /************************************************************************/ /* Function : process_command_line */ /* Purpose : Read the arguments from the command line */ /* Inputs : argc, argv from main() routine */ /* Outputs : TRUE if arguments OK, else FALSE */ /************************************************************************/ MBool process_command_line ( Int argc, char **argv ) { Int i, baud; while ( (i = getopt(argc, argv, "a:b:f:p:t:")) != EOF ) switch( i ) { case 'a': tncaddr = optarg; break; case 'b': if ( !set_baud(&tnc_term, atoi(optarg)) ) return( FALSE ); break; case 'f': cmdfile = optarg; break; case 'p': tncfile = optarg; break; case 't': timeout = 60 * atoi(optarg); break; default: return( FALSE ); } return( TRUE ); } /* process_command_line() */ /****************************************************************************/ /* Function : find_str */ /* Purpose : Find target string embedded in source string, case insens */ /* Inputs : Source string ptr, Target string ptr */ /* Outputs : NULL if strings don't match, else ptr to next char of source*/ /****************************************************************************/ char * find_str( char *src, char *tgt ) { Reg char *p, *p1, *q; for ( p1 = src; *p1; p1++ ) { for( p = p1, q = tgt; ; p++, q++ ) { if ( *q == '\0' ) return( p ); if ( *p == '\0' ) return( NULL ); if ( toupper(*p) != toupper(*q) ) break; } } return( NULL ); } /* find_str() */ /************************************************************************/ /* Function : gets_tnc_tmout */ /* Purpose : Read one line from TNC with timeout */ /* Inputs : Buffer, length, timeout (seconds) */ /* Outputs : Number of characters read, or ERROR */ /* Comment : Needs a buffer of length len+1 (for '\0') */ /************************************************************************/ Int gets_tnc_tmout( char *buf, Int len, Int tmout ) { time_t start, curtime; Int i, rtn; char c; time( &start ); /* Get start time */ for ( rtn = 0; rtn < len; ) { if ( (i = read(tfd, &buf[rtn], 1)) < 0 ) /* Read one character */ break; if ( i > 0 ) /* If got character, */ { c = buf[rtn++]; /* increment char count */ if ( c == '\n' ) /* look for end of line */ break; if ( c == '\r' ) { /* If CR, */ buf[rtn++] = '\n'; /* insert LF */ break; } } time( &curtime ); /* Get time */ if ( curtime > start + tmout ) /* If timed out, return */ break; } buf[rtn] = '\0'; /* Insert EOS */ if ( rtn > 0 ) { /* Echo to stdout */ printf( "%s", buf ); fflush( stdout ); } return( rtn ); /* Return # chars */ } /* gets_tnc_tmout() */ /************************************************************************/ /* Function : write_tnc */ /* Purpose : Write a line to the TNC, echo to stdout */ /* Inputs : String to write */ /* Outputs : OK or ERROR */ /************************************************************************/ Status write_tnc( char *s ) { Reg Nat32 rtn; Reg char *p, *q; rtn = write( tfd, s, strlen(s) ); if ( (p = strdup(s)) != NULL ) { while ( (q = strchr(p, '\r')) != NULL ) *q = '\n'; printf( "%s", p ); fflush( stdout ); free(p); } return( (rtn == strlen(s)) ? OK : ERROR ); } /* write_tnc() */ /************************************************************************/ /* Function : tnc_cmd_mode */ /* Purpose : Send ^C to TNC to go into command mode */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Status tnc_cmd_mode( Void ) { Int32 i; if ( write_tnc("\003\r") != OK ) /* Send ctrl-C to TNC */ return( ERROR ); for ( i = 0; i < 10; i++ ) /* Wait for "cmd:" prompt*/ { if ( gets_tnc_tmout(rbuf, 4, 10) <= 0 ) return( ERROR ); if ( find_str(rbuf, "cmd:") != NULL ) return( OK ); } return( ERROR ); } /* tnc_cmd_mode() */ /************************************************************************/ /* Function : send_tnc_cmds */ /* Purpose : Send commands to the TNC */ /* Inputs : Ptr to cmds, number of cmds */ /* Outputs : OK or ERROR */ /************************************************************************/ Status send_tnc_cmds( char *cmds[], Int num ) { Int i; Status rtn; rtn = tnc_cmd_mode(); /* Go into command mode */ for ( i = 0; i < num; i++ ) /* Send commands to TNC */ { write_tnc( cmds[i] ); gets_tnc_tmout( rbuf, BUFSIZE, 1 ); /* Discard any replys */ } return( OK ); } /* send_tnc_cmds() */ /************************************************************************/ /* Function : tnc_status */ /* Purpose : Get STATus message from TNC */ /* Inputs : None */ /* Outputs : Status of TNC, or ERROR */ /* Comment : Leaves TNC in command mode */ /************************************************************************/ Int tnc_status( Void ) { char *p; Int res; write_tnc( "STAT\r" ); /* Ask for status */ res = -1; /* Initialize result */ while ( gets_tnc_tmout(rbuf, BUFSIZE, 10) != ERROR ) if ( (p = find_str(rbuf, "STAT")) != NULL ) if ( (p = strchr(p, '$')) != NULL ) if ( sscanf(p+1, "%x", &res) == 1 ) break; gets_tnc_tmout( rbuf, BUFSIZE, 10 ); /* Clear tnc buffer */ return( res ); } /* tnc_status() */ /************************************************************************/ /* Function : disconnect_tnc */ /* Purpose : Break TNC connection */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Status disconnect_tnc( Void ) { Int i; Status rtn; rtn = tnc_cmd_mode(); /* Go into command mode */ if ( write_tnc("D\r") != OK ) /* Make sure we're */ return( ERROR ); /* disconnected */ for ( i = 10; i; i-- ) { if ( tnc_status() == 0 ) return( rtn ); sleep( 2 ); } return( ERROR ); } /* disconnect_tnc() */ /************************************************************************/ /* Function : connect_tnc */ /* Purpose : Put TNC into converse mode */ /* Inputs : None */ /* Outputs : OK or ERROR */ /************************************************************************/ Status connect_tnc( Void ) { time_t start, curtime; disconnect_tnc(); /* Make sure disconnected*/ time( &start ); /* Get time */ sprintf(rbuf, "C %s\r", tncaddr); /* Send connect message */ if ( write_tnc(rbuf) != OK ) return( ERROR ); while ( time(&curtime) < start + timeout ) /* Loop until connect */ { /* or timeout */ if ( aborted ) /* If program aborted, */ return( ERROR ); /* return ERROR */ gets_tnc_tmout( rbuf, BUFSIZE, timeout - (curtime - start) ); if ( find_str(rbuf, "DISCONNECTED") != NULL ) { sprintf(rbuf, "C %s\r", tncaddr); if ( write_tnc(rbuf) != OK ) return( ERROR ); } else if ( find_str(rbuf, "CONNECTED") != NULL ) return( OK ); } return( ERROR ); /* Timed out. Error */ } /* connect_tnc() */ /************************************************************************/ /* Function : wait_for_prompt */ /* Purpose : Wait for OASIS prompt or "DISCONNECTED" message */ /* Inputs : None */ /* Outputs : OK or ERROR */ /* Comments : Error if "DISCONNECTED" or no data for timeout seconds */ /************************************************************************/ Status wait_for_prompt( Void ) { time_t datatime, curtime; Int i, j; char c; time( &datatime ); /* Get start time */ j = 0; while ( !aborted && (time(&curtime) <= datatime + prompt_tmout) ) { if ( (i = read(tfd, &c, 1)) > 0 ) /* Read one character */ { /* If got character, */ rbuf[j++] = c; /* Store it */ rbuf[j] = '\0'; /* Mark end of string */ if ( c != '\r' ) putchar( c ); /* Echo it to stdout */ datatime = curtime; /* Save time of last data*/ if ( find_str(rbuf, OPROMPT) != NULL ) { /* Look for prompt */ while ( read(tfd, &c, 1) > 0 ) /* If got it, throw away*/ ; /* extra chars (spaces)*/ return( OK ); /* and return OK */ } if ( find_str(rbuf, "DISCONNECTED") != NULL ) return( DOWNLOAD_ERR ); /* Look for DISCON msg */ if ( (c == '\r') || (c == '\n') || (j > BUFSIZE) ) { j = 0; fflush(stdout); } } /* if */ } /* while */ return( TIMEOUT_ERR ); } /* wait_for_prompt() */ /************************************************************************/ /* Function : sendUsrCmds */ /* Purpose : Send user commands, copy to stdout */ /* Inputs : None */ /* Outputs : Return code for exit() */ /************************************************************************/ Status sendUsrCmds( Void ) { FILE *cmdfp = stdin; Reg char *p; if ( (cmdfile == NULL) || ((cmdfp = fopen(cmdfile, "r")) == (FILE *)NULL) ) cmdfp = stdin; while ( fgets(rbuf, BUFSIZE, cmdfp) != NULL ) { if ( (p = strchr(rbuf, '\n')) != NULL ) *p++ = '\r'; if ( (p = strchr(rbuf, '\r')) == NULL ) p = &rbuf[strlen(rbuf)]; *p++ = '\r'; *p = '\0'; if ( write_tnc(rbuf) != OK ) return( DOWNLOAD_ERR ); if ( wait_for_prompt() == DOWNLOAD_ERR ) return( DOWNLOAD_ERR ); } return( OK ); } /* sendUsrCmds() */ /************************************************************************/ /* Function : tnc_read */ /* Purpose : SIGIO handler */ /* Inputs : Signal number received */ /* Outputs : None */ /************************************************************************/ Void tnc_read( Void ) { Int32 nbytes; char c; if ( (nbytes = read(tfd, &c, 1)) > 0 ) { rbuf[rcnt++] = c; if ( echo && (c != '\r') ) putchar( c ); if ( rcnt > BUFSIZE ) rcnt = 0; rbuf[rcnt] = '\0'; } else if ( nbytes == -1 ) { aborted = TRUE; perror( "Read error in SIGIO handler\n" ); } } /************************************************************************/ /* Function : quit */ /* Purpose : SIGTERM handler */ /* Inputs : Signal number received */ /* Outputs : None */ /************************************************************************/ Void quit( Int sig ) { aborted = TRUE; } /* quit() */ @ 2.9 log @Archiving sources after M2/M3 & Eqpac deployments of 1998 @ text @d4 1 a4 1 /* $Header: sendoasis.c,v 2.8 98/03/17 11:11:43 bobh Exp $ */ d9 1 a9 1 /* $Revision: 2.8 $ */ d15 3 d44 1 d73 1 d123 1 a123 1 printf("OASIS command program $Revision: 2.8 $\n"); d504 1 a504 1 while ( !aborted && (time(&curtime) <= datatime + timeout) ) d529 1 a529 1 return( DOWNLOAD_ERR ); d564 1 a564 1 if ( wait_for_prompt() != OK ) @