Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <sys/time.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <termios.h>
- #include <unistd.h>
- #include <errno.h>
- #include <signal.h>
- #include <sys/select.h>
- #include <ctype.h>
- #include <getopt.h>
- #define VERSION "2.6.0"
- /* values for parity */
- #define SERIAL_NO_PARITY 1
- #define SERIAL_EVEN_PARITY 2
- #define SERIAL_ODD_PARITY 4
- /* values for data bits */
- #define SERIAL_8_DATA_BITS 8
- #define SERIAL_7_DATA_BITS 7
- /* values for stop bits */
- #define SERIAL_1_STOP_BITS 1
- #define SERIAL_2_STOP_BITS 2
- /* flow control */
- #define FLOW_CONTROL_NONE 1
- #define FLOW_CONTROL_HARDWARE 2
- #define FLOW_CONTROL_SOFTWARE 3
- #define FALSE 0
- #define TRUE 1
- #define DEFAULT_BAUD_RATE B9600
- //#define BAUD_RATE B19200
- //#define BAUD_RATE B38400
- #define NON_BLOCKING_SERIAL
- char serial_port[FILENAME_MAX+1];
- char logfile_name[FILENAME_MAX+1];
- /* log output to file */
- int opt_log_output = FALSE;
- /* dump output as hex */
- int opt_hex_output = TRUE;
- /* strip high bit from all chars sent to stdout */
- int opt_strip_high_bit = FALSE;
- /* default is to transmit CRLF on CR from stdin; when true, only the CR is
- * transmitted to remote
- */
- int opt_bare_cr = FALSE;
- speed_t baudrate = DEFAULT_BAUD_RATE;
- /* at some point, could make these command line configurable */
- int parity = SERIAL_NO_PARITY;
- //int databits = SERIAL_7_DATA_BITS;
- int databits = SERIAL_8_DATA_BITS;
- int stopbits = SERIAL_1_STOP_BITS;
- //int flow_control = FLOW_CONTROL_SOFTWARE;
- //int flow_control = FLOW_CONTROL_HARDWARE;
- int flow_control = FLOW_CONTROL_NONE;
- int main_quit = 0;
- typedef struct {
- const char *str;
- int len; /* string length of str */
- speed_t speed;
- } BaudRate;
- BaudRate baudrates[] = {
- { "110", 3, B110 },
- { "150", 3, B150 },
- { "300", 3, B300 },
- { "600", 3, B600 },
- { "1200", 4, B1200 },
- { "2400", 4, B2400 },
- { "4800", 4, B4800 },
- { "9600", 4, B9600 },
- { "19200", 5, B19200 },
- { "38400", 5, B38400 },
- { "57600", 5, B57600 },
- { "115200", 6, B115200},
- { "230400", 6, B230400},
- };
- const unsigned char CR = '\r';
- const unsigned char LF = '\n';
- #if defined linux || defined unix || defined __GNUC__
- void signal_term( int signum )
- {
- fprintf( stderr, "signal!\n" );
- main_quit = 1;
- }
- void init_signals( void )
- {
- int uerr;
- struct sigaction sigterm;
- struct sigaction sigint;
- memset( &sigterm, 0, sizeof(sigterm) );
- sigterm.sa_handler = signal_term;
- uerr = sigaction( SIGTERM, &sigterm, NULL );
- if( uerr != 0 ) {
- perror( "sigaction(SIGTERM)" );
- exit(1);
- }
- memset( &sigint, 0, sizeof(sigint) );
- sigint.sa_handler = signal_term;
- uerr = sigaction( SIGINT, &sigint, NULL );
- if( uerr != 0 ) {
- perror( "sigaction(SIGINT)" );
- exit(1);
- }
- }
- #endif
- int serial_open_port( void )
- {
- struct termios oldtio, newtio;
- int fd;
- /* stupid human check -- I've been running this thing
- * as root (very very dumb) so I don't want to accidently
- * write DNP to /dev/hda1 or something equally tragic.
- */
- // if( strncmp( path, "/dev/ttyS", 9 ) != 0 ) {
- // LOG_MESSAGE1( LOG_ERR, "\"%s\" not a serial port.", path );
- // return ERR_FAIL;
- // }
- /* davep 29-Apr-2009 ; temp debug */
- fprintf( stderr, "%s opening %s\n", __FUNCTION__, serial_port );
- /* open serial port */
- #ifdef NON_BLOCKING_SERIAL
- fd = open( serial_port, O_RDWR|O_NOCTTY|O_NONBLOCK );
- #else
- fd = open( serial_port, O_RDWR|O_NOCTTY );
- #endif
- if( fd < 0 ) {
- fprintf( stderr, "open() of %s failed : %s",
- serial_port, strerror(errno) );
- return -1;
- }
- /* davep 29-Apr-2009 ; temp debug */
- fprintf( stderr, "%s opened %s successfully\n", __FUNCTION__, serial_port );
- tcgetattr( fd, &oldtio );
- memset( &newtio, 0, sizeof(newtio) );
- newtio.c_cflag = CLOCAL | CREAD ;
- /* parity */
- switch( parity ) {
- case SERIAL_NO_PARITY :
- /* nothing -- default is no parity */
- break;
- case SERIAL_EVEN_PARITY :
- newtio.c_cflag |= PARENB;
- break;
- case SERIAL_ODD_PARITY :
- newtio.c_cflag |= PARENB | PARODD;
- break;
- default :
- assert( 0 );
- }
- /* data bits */
- if( databits == SERIAL_8_DATA_BITS ) {
- newtio.c_cflag |= CS8;
- }
- else if( databits == SERIAL_7_DATA_BITS ) {
- newtio.c_cflag |= CS7;
- }
- else {
- assert( 0 );
- }
- /* stop bits */
- if( stopbits == SERIAL_1_STOP_BITS ) {
- /* nothing -- default is 1 stop bit */
- }
- else if( stopbits == SERIAL_2_STOP_BITS ) {
- newtio.c_cflag |= CSTOPB;
- }
- else {
- assert( 0 );
- }
- /* hardware flow control? */
- if( flow_control==FLOW_CONTROL_HARDWARE ) {
- newtio.c_cflag |= CRTSCTS;
- }
- newtio.c_lflag = 0;
- /* no additional lflags */
- newtio.c_iflag = 0; // | IXON | IXANY | IXOFF | IMAXBEL;
- /* software flow control? */
- if( flow_control==FLOW_CONTROL_SOFTWARE ) {
- newtio.c_iflag |= (IXON | IXOFF | IXANY);
- }
- newtio.c_oflag = 0;
- /* no additional oflags */
- cfsetospeed( &newtio, baudrate );
- cfsetispeed( &newtio, baudrate );
- #ifndef NON_BLOCKING_SERIAL
- newtio.c_cc[VMIN] = 1; /* block until this many chars recvd */
- newtio.c_cc[VTIME] = 0; /* inter character timer unused */
- #endif
- tcflush( fd, TCIFLUSH );
- tcsetattr( fd, TCSANOW, &newtio );
- return fd;
- }
- int baud_string_to_baud( char *baudstring, speed_t *baudrate )
- {
- int i;
- for( i=0 ; i<sizeof(baudrates)/sizeof(BaudRate) ; i++ ) {
- if(strncasecmp(baudrates[i].str,baudstring,baudrates[i].len )==0) {
- /* found it */
- *baudrate = baudrates[i].speed;
- return 0;
- }
- }
- return -1;
- }
- const char *baud_to_baud_string( speed_t baudrate )
- {
- int i;
- for( i=0 ; i<sizeof(baudrates)/sizeof(BaudRate) ; i++ ) {
- if( baudrates[i].speed == baudrate ) {
- /* found it */
- return baudrates[i].str;
- }
- }
- return NULL;
- }
- void print_usage( void )
- {
- int i;
- printf( "ttysniff %s (%s) - read and dump data from serial port.\n",
- VERSION, __DATE__ );
- printf( "usage: ttysniff [-options] [-l logfile] [-b baud] [-f flowcontrol] path\n" );
- printf( " -h show this help\n" );
- printf( " -p print data as readable (default is to print as hex)\n" );
- printf( " -l logfile log traffic to binary file\n" );
- printf( " -b baudrate set baud rate (default=%s)\n",
- baud_to_baud_string(DEFAULT_BAUD_RATE) );
- printf( " -7 7 data bits\n" );
- printf( " -8 8 data bits (default)\n" );
- printf( " -f [hard|soft] enable hardware (RTS/CTS) or software (XON/XOFF) flow control\n" );
- printf( " (default is no flow control)\n" );
- printf( " --strip-high-bit remove high bit (1<<8) from chars before printing\n" );
- printf( " (doesn't effect logging to file or printing as hex)\n" );
- printf( " --bare-cr don't send CRLF when reading CR from stdin\n" );
- printf( " (default is to send CRLF when reading CR on input)\n" );
- printf( " path path to serial port (e.g., /dev/ttyS0)\n" );
- printf( "\n" );
- printf( "Available baud rates are: " );
- for( i=0 ; i<sizeof(baudrates)/sizeof(BaudRate) ; i++ ) {
- printf( "%s ", baudrates[i].str );
- }
- printf( "\n" );
- }
- static int str_match( const char *s1, const char *s2, size_t maxlen )
- {
- /* Strings must exactly match and must be exactly maxlen. The maxlen+1
- * finds strings longer than maxlen
- */
- if( strnlen(s1,maxlen+1)<=maxlen &&
- strnlen(s2,maxlen+1)<=maxlen &&
- strncmp(s1,s2,maxlen)==0 ){
- return TRUE;
- }
- return FALSE;
- }
- static int parse_long_option( const char *long_opt_name,
- const char *long_opt_value )
- {
- if( str_match( long_opt_name, "strip-high-bit", 14 ) ) {
- opt_strip_high_bit = TRUE;
- }
- else if( str_match( long_opt_name, "bare-cr", 8 ) ) {
- /* don't send a LF to remote side when read CR from stdin */
- opt_bare_cr = TRUE;
- }
- return 0;
- }
- int parse_args( int argc, char *argv[] )
- {
- int retcode;
- char c;
- static struct option long_options[] = {
- { "strip-high-bit", 0, 0, 0 }, /* strip high bit (c&0x7f) */
- { "bare-cr", 0, 0, 0 }, /* don't send extra LF on reading CR from stdin */
- { 0, 0, 0, 0 },
- };
- int long_index;
- if( argc == 1 ) {
- print_usage();
- exit(1);
- }
- baudrate = DEFAULT_BAUD_RATE;
- while( 1 ) {
- c = getopt_long( argc, argv, "hpl:b:78f:", long_options, &long_index );
- if( c==-1 )
- break;
- switch( c ) {
- case 0 :
- /* handle long option */
- retcode = parse_long_option( long_options[long_index].name, optarg );
- if( retcode != 0 ) {
- exit(1);
- }
- break;
- case 'h' :
- print_usage();
- exit(1);
- break;
- case 'l' :
- /* save output file name */
- strncpy( logfile_name, optarg, FILENAME_MAX );
- opt_log_output = TRUE;
- break;
- case 'p' :
- opt_hex_output = FALSE;
- break;
- case 'b' :
- /* convert baud rate string to baud rate number */
- if( baud_string_to_baud( optarg, &baudrate ) != 0 ) {
- fprintf( stderr, "Invalid baud rate \"%s\"\n", optarg );
- exit(1);
- }
- break;
- case '7' :
- /* 7 data bits */
- databits = SERIAL_7_DATA_BITS;
- break;
- case '8' :
- /* 8 data bits */
- databits = SERIAL_8_DATA_BITS;
- break;
- case 'f' :
- if( strncmp( optarg, "hard", 4 ) == 0 ) {
- flow_control = FLOW_CONTROL_HARDWARE;
- }
- else if( strncmp( optarg, "soft", 4 ) == 0 ) {
- flow_control = FLOW_CONTROL_SOFTWARE;
- }
- else {
- fprintf( stderr, "Invalid flow control \"%s\"\n", optarg );
- exit(1);
- }
- break;
- case '?' :
- print_usage();
- exit(1);
- break;
- default :
- break;
- }
- }
- /* get serial port name */
- if (optind < argc) {
- strncpy( serial_port, argv[optind++], FILENAME_MAX );
- }
- else {
- fprintf( stderr, "You must specify a serial port.\n" );
- print_usage();
- exit(1);
- }
- /* XXX temp debug */
- // fprintf( stderr, "baud=%ld port=%s\n", baudrate, serial_port );
- return 0;
- }
- int
- terminal_to_raw( struct termios *save_tios )
- {
- struct termios newtios;
- int stdin_fileno;
- int retcode;
- stdin_fileno = fileno(stdin);
- /* get a copy well save until we restore stdin at exit */
- retcode = tcgetattr( stdin_fileno, save_tios );
- if( retcode < 0 ) {
- fprintf( stderr, "tcgetattr() failed to get stdin term attributes: %d %s\n",
- errno, strerror(errno));
- return -1;
- }
- /* get them again so we can muck with them */
- retcode = tcgetattr( stdin_fileno, &newtios );
- if( retcode < 0 ) {
- fprintf( stderr, "tcgetattr() failed to get stdin term attributes: %d %s\n",
- errno, strerror(errno));
- return -1;
- }
- cfmakeraw( &newtios );
- /* set stdin to raw */
- retcode = tcsetattr( stdin_fileno, TCSANOW, &newtios );
- if( retcode < 0 ) {
- fprintf( stderr, "tcsetattr() failed to set stdin term attributes: %d %s\n",
- errno, strerror(errno));
- return -1;
- }
- return 0;
- }
- int main( int argc, char *argv[] )
- {
- int err;
- FILE *binfile=NULL;
- int stdin_fileno, fd;
- unsigned char databyte;
- int count;
- fd_set read_fds;
- int max_fd;
- struct termios stdin_tios;
- parse_args( argc, argv );
- init_signals();
- if( opt_log_output ) {
- binfile = fopen( logfile_name, "a" );
- if( binfile == NULL ) {
- fprintf( stderr, "Unable to open log file \"%s\" : %s\n",
- logfile_name, strerror(errno) );
- exit(1);
- }
- setbuf( binfile, NULL );
- }
- fd = serial_open_port();
- if( fd < 0 ) {
- /* serial_open_port() displays error */
- exit(1);
- }
- /* set the terminal to raw so we can get single keystrokes */
- fprintf( stderr, "setting stdin to raw...\n" );
- memset( &stdin_tios, 0, sizeof(struct termios) );
- terminal_to_raw( &stdin_tios );
- /* davep 20-July-06 ; XXX TEMPORARY FOR DEBUGGING kick off some activity */
- // write( fd, "scan var print\r\n", 16 );
- setbuf( stdout, NULL );
- count = 0;
- stdin_fileno = fileno(stdin);
- while( !main_quit ) {
- // fprintf( stderr, "stdin=%d\n", fileno(stdin));
- FD_ZERO( &read_fds );
- FD_SET( stdin_fileno, &read_fds );
- FD_SET( fd, &read_fds );
- max_fd = stdin_fileno;
- if( fd > max_fd ) {
- max_fd = fd;
- }
- err = select( max_fd+1, &read_fds, NULL, NULL, NULL );
- if( err<0 ) {
- fprintf( stderr, "select err=%d errno=%d (%s)\r\n", err, errno,
- strerror(errno) );
- continue;
- }
- if( FD_ISSET( stdin_fileno, &read_fds ) ) {
- err = read( stdin_fileno, &databyte, 1 );
- if( err <= 0 ) {
- fprintf( stderr, "read stdin err=%d errno=%d (%s)\r\n",
- err, errno, strerror(errno) );
- break;
- }
- if( databyte == 0x03 ) {
- /* Ctrl-C? */
- break;
- }
- write( fd, &databyte, 1 );
- if( databyte==CR && !opt_bare_cr ) {
- write( fd, &LF, 1 );
- }
- }
- if( FD_ISSET( fd, &read_fds ) ) {
- err = read( fd, &databyte, 1 );
- if( err <= 0 ) {
- fprintf( stderr, "read fd err=%d errno=%d (%s)\r\n",
- err, errno, strerror(errno) );
- break;
- }
- if( opt_hex_output ) {
- /* There is something weird in printf(). I want to see 0x00 and it
- * prints "0" instead. Messes up my pretty screen alignment.
- */
- if( databyte ) {
- #ifdef PRINT_0X
- printf( "%#04x ", databyte );
- }
- else {
- printf( "0x00 " );
- }
- #else
- printf( "%02x ", databyte );
- }
- else {
- printf( "00 " );
- }
- #endif
- }
- else {
- /* buyer beware -- just print whatever we get */
- /* added some simple "filtering"; TODO add regex filtering so
- * really annoying stuff never hits human eyeballs
- */
- int printit = 1;
- /* davep 10-May-2012 ; bell pissing me off */
- if( databyte==0x07 ) {
- printit = 0;
- }
- /* davep 19-aug-2011 ; found a platform that uses \n\r not \r\n
- * (buh?) so filter out the 0x0d
- */
- if( databyte==0x0a ) {
- printf( "%c", 0x0d );
- }
- if( databyte==0x0d ) {
- printit = 0;
- }
- /* davep 27-Oct-2011 ; quiet down people doing obnoxious stuff like:
- *
- * ******** color_pipe_set_config ENTRY config: 0x5fae64
- *
- */
- // if( databyte == '*' ) {
- // printit = 0;
- // }
- /* davep 01-Aug-2010 ; I did the 0x7f a while ago (strips the
- * 8th bit) because our newer hardware has issues and the 8th
- * bit flips up and down randomly.
- */
- if( printit ) {
- if( opt_strip_high_bit ) {
- printf( "%c", databyte&0x7f );
- }
- else {
- printf( "%c", databyte );
- }
- }
- }
- if( opt_log_output ) {
- fwrite( &databyte, 1, 1, binfile );
- fflush( binfile );
- }
- }
- count++;
- }
- close( fd );
- if( opt_log_output ) {
- fclose( binfile );
- }
- /* set stdin back to starting point */
- fprintf( stderr, "restoring stdin to previous state\r\n" );
- err = tcsetattr( stdin_fileno, TCSANOW, &stdin_tios );
- if( err < 0 ) {
- fprintf( stderr, "tcsetattr() failed to set stdin term attributes: %d %s\n",
- errno, strerror(errno));
- /* keep going and hope for the best */
- }
- printf( "\nbye!\n" );
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement