head 1.1; access ; symbols ; locks ; strict; comment @ * @; 1.1 date 92.02.26.10.15.24; author hebo; state Rel; branches ; next 1.0; 1.0 date 92.02.25.10.47.00; author hebo; state Rel; branches ; next ; desc @Program to send differential GPS corrections on packet radio @ 1.1 log @Added file locks for device ports @ text @/****************************************************************************/ /* Copyright 1992 MBARI */ /****************************************************************************/ /* $Header: gps.c,v 1.0 92/02/25 10:47:00 hebo Rel $ */ /* Summary : Program to send differential GPS corrections on packet radio */ /* Filename : gps.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 1.0 $ */ /* Created : 02/11/92 */ /****************************************************************************/ /* Modification History: */ /* 11feb92 rah - created */ /* $Log: gps.c,v $ * Revision 1.0 92/02/25 10:47:00 10:47:00 hebo (Bob Herlien) * Initial revision */ /****************************************************************************/ #define _HPUX_SOURCE /* termio.h (at least) needs this */ #include /* Standard I/O */ #include /* For exit() */ #include /* For FD_ISSET, etc */ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* For timeout */ #include /* For terminal I/O stuff */ #include /* For open() stuff */ #include /* For ioctl() */ #include /* For NOFILE */ #include /* For strcmp() */ #include /* For signals */ #define GPS_DEV "gps" /* Default GPS device file */ #define RADIO_DEV "tnc" /* Default radio device file */ #define BUFSIZE 512 /* Size of line buffer */ typedef int Status; /* Status return, normally OK or ERROR*/ /********************************/ /* External Functions */ /********************************/ /* From port.c */ Extern Boolean 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 time_t duration = (8 * 60); /* Time in minutes we should execute*/ MLocal char *gpsfile = GPS_DEV; /* GPS device file */ MLocal char *radiofile = RADIO_DEV; /* Radio device file */ MLocal Int gfd = ERROR; /* GPS file descriptor */ MLocal Int rfd = ERROR; /* Radio file descriptor */ MLocal Int done = -1; /* Global quit flag */ MLocal char rwbuf[BUFSIZE]; /* Read/write line buffer */ MLocal struct termio gps_term = /* Termio characteristics for GPS */ { IGNPAR | ISTRIP | INLCR, /* c_iflag */ 0, /* c_oflag */ B9600 | CS8 | CREAD | CLOCAL, /* c_cflag */ ICANON | NOFLSH, /* c_lflag */ 0, /* c_line, HP has no line disciplines*/ {0, 0, 0, 0, 0, '\r', 0, 0} /* control chars (CR for EOL) */ }; MLocal struct termio radio_term = /* Termio characteristics for radio */ { IGNPAR | INLCR | IXON, /* 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, BUFSIZE/2, 10, 0, 0} /* control chars (1 second timeout) */ }; MLocal struct termio gps_save, radio_save; /* Place to save terminal charac.*/ MLocal char *tnc_cmds[] = { "EC OFF\r", "M OFF\r" }; /********************************/ /* Forward Declarations */ /********************************/ Boolean process_command_line ( Int argc, char **argv ); Void use_msg( Void ); Boolean detach_terminal( Int fd1, Int fd2 ); Status connect_tnc( Int fd ); Status copy_data( Int infd, Int outfd ); Void quit( Int sig ); /************************************************************************/ /* Function : main */ /* Purpose : Main routine */ /* Inputs : argc, argv */ /* Outputs : none */ /************************************************************************/ Void main( Int argc, char **argv ) { time_t start_time, curtime; Int childpid; if ( !process_command_line(argc, argv) ) { use_msg(); exit( 1 ); } #ifndef DEBUG if ( (childpid = fork()) < 0 ) /* Fork to detach terminal */ { fprintf(stderr, "Can't fork child process\n"); exit( 3 ); } else if ( childpid > 0 ) /* Parent proecess exits */ exit( 0 ); #endif signal(SIGTERM, quit); /* Catch terminate signals */ signal(SIGHUP, quit); signal(SIGINT, quit); signal(SIGQUIT, quit); done = -1; if ( (gfd = get_port(gpsfile, O_RDONLY, &gps_term, &gps_save)) == ERROR ) exit( 3 ); if ((rfd = get_port(radiofile, O_RDWR, &radio_term, &radio_save)) == ERROR) { release_port( gpsfile, gfd, &gps_save ); exit( 3 ); } if ( connect_tnc(rfd) != OK ) { fprintf( stderr, "Couldn't establish radio communication\n" ); done = 3; } if ( time(&start_time) == (time_t)ERROR ) { fprintf( stderr, "Couldn't get time of day\n" ); done = 3; } if ( !detach_terminal(gfd, rfd) ) done = 3; while ( done < 0 ) { if ( copy_data(gfd, rfd) == ERROR ) done = 3; time( &curtime ); if ( curtime > start_time + (60 * duration) ) done = 0; } disconnect_tnc( rfd ); release_port( gpsfile, gfd, &gps_save ); release_port( radiofile, rfd, &radio_save ); exit( done ); } /* main() */ /************************************************************************/ /* Function : use_msg */ /* Purpose : Print Usage Message */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void use_msg( Void ) { fprintf(stderr, "Usage: gps [-g gps_device] [-r radio_device] [-t minutes_on] "); fprintf(stderr, "[-bg gps_baud] [-br radio_baud]\n\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 */ /************************************************************************/ Boolean process_command_line ( Int argc, char **argv ) { Int i, baud; opterr = 0; while ( (i = getopt(argc, argv, "b:g:r:t:")) != EOF ) switch( i ) { case 'b': if ( sscanf(optarg, "g %d", &baud) >0 ) { if ( set_baud(&gps_term, baud) ) break; else return( FALSE ); } else if ( sscanf(optarg, "r %d", &baud) > 0 ) { if ( set_baud(&radio_term, baud) ) break; else return( FALSE ); } return( FALSE ); case 'g': gpsfile = optarg; break; case 'r': radiofile = optarg; break; case 't': duration = atoi(optarg); break; default: return( FALSE ); } return( TRUE ); } /* process_command_line() */ /************************************************************************/ /* Function : Detach Terminal */ /* Purpose : Fork a child process, detach it from controlling terminal*/ /* Inputs : Two file descriptors to leave open */ /* Outputs : TRUE if OK, else FALSE */ /* Comments : Calling process exits, user returns to shell */ /************************************************************************/ Boolean detach_terminal( Int fd1, Int fd2 ) { #ifndef DEBUG Int fd; if ( setpgrp() == ERROR ) /* Disassociate child from*/ { /* controlling terminal */ fprintf(stderr, "Can't change process group\n"); return( FALSE ); } for ( fd = 0; fd < NOFILE; fd++ ) /* Close all open files */ if ( (fd != fd1) && (fd != fd2) ) /* except 2 device files */ close( fd ); chdir( "/" ); /* Make sure we don't interfere */ /* with unmounting a file system */ #endif return( TRUE ); } /* detach_terminal() */ /************************************************************************/ /* Function : read_tmout */ /* Purpose : Read from a file descriptor with timeout */ /* Inputs : File descriptor, buffer, length, timeout (seconds) */ /* Outputs : Number of characters read, or ERROR */ /************************************************************************/ Int read_tmout( Int fd, char *buf, Int len, Int tmout ) { fd_set readfds; struct timeval timeout; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); timeout.tv_sec = tmout; timeout.tv_usec = 0; if ( select(fd+1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 0 ) return( ERROR ); if ( FD_ISSET(fd, &readfds) ) return( read(fd, buf, len) ); else return( ERROR ); } /* read_tmout() */ /************************************************************************/ /* Function : disconnect_tnc */ /* Purpose : Break TNC connection */ /* Inputs : TNC file descriptor */ /* Outputs : OK or ERROR */ /************************************************************************/ Status disconnect_tnc( Int fd ) { if ( write(fd, "\003", 1) != 1 ) return( ERROR ); if ( read(fd, rwbuf, BUFSIZE) < 0 ) return( ERROR ); if ( sscanf(rwbuf, "cmd:") < 0 ) return( ERROR ); return( OK ); } /* disconnect_tnc() */ /************************************************************************/ /* Function : connect_tnc */ /* Purpose : Put TNC into converse mode */ /* Inputs : TNC file descriptor */ /* Outputs : OK or ERROR */ /************************************************************************/ Status connect_tnc( Int fd ) { Int i; disconnect_tnc( fd ); /* Go to command mode */ /* Send init commands to TNC*/ for ( i = 0; i < (sizeof(tnc_cmds)/sizeof(char *)); i++ ) write(fd, tnc_cmds[i], strlen(tnc_cmds[i])); read( fd, rwbuf, BUFSIZE ); /* Discard any replys */ if ( write(fd, "K\r", 2) == 2 ) /* Go to converse mode */ return( OK ); else return( ERROR ); } /* connect_tnc() */ /************************************************************************/ /* Function : copy_data */ /* Purpose : Copy data from input file to output file */ /* Inputs : Input file descriptor, output file descriptor */ /* Outputs : OK or ERROR */ /************************************************************************/ Status copy_data( Int infd, Int outfd ) { Int n; if ( (n = read_tmout(infd, rwbuf, BUFSIZE, 10)) < 0 ) return( ERROR ); if ( n > 0 ) if ( write(outfd, rwbuf, n) < 0 ) return( ERROR ); return( OK ); } /* copy_data() */ /************************************************************************/ /* Function : quit */ /* Purpose : SIGTERM handler */ /* Inputs : Signal number received */ /* Outputs : None */ /************************************************************************/ Void quit( Int sig ) { done = 1; } /* quit() */ @ 1.0 log @Initial revision @ text @d4 1 a4 1 /* $Header: gps.c,v 1.1 92/02/25 10:45:34 hebo Exp $ */ d9 1 a9 1 /* $Revision: 1.1 $ */ d15 1 a15 1 * Revision 1.1 92/02/25 10:45:34 10:45:34 hebo (Bob Herlien) a16 1 * d33 1 d35 2 a36 2 #define GPS_DEV "/dev/gps" /* Default GPS device file */ #define RADIO_DEV "/dev/tnc" /* Default radio device file */ d43 10 d68 3 a92 11 MLocal struct baudstruct { Int ibaud; Nat16 bflag; } bauds[] = { {50, B50}, {75, B75}, {110, B110}, {134, B134}, {150, B150}, {200, B200}, {300, B300}, {600, B600}, {900, _B900}, {1200, B1200}, {1800, B1800}, {2400, B2400}, {3600, _B3600}, {4800, B4800}, {7200, _B7200}, {9600, B9600}, {19200, B19200}, {38400, B38400} }; a101 2 Int setup_device( char *device, Int mode, struct termio *setup, struct termio *save ); a103 1 Status disconnect_tnc( Int fd ); d105 1 a116 1 Int gfd, rfd; /* GPS, radio file descriptors */ d118 1 d126 9 a134 3 if ( (gfd = setup_device(gpsfile, O_RDONLY, &gps_term, &gps_save)) == ERROR ) exit( 1 ); d136 5 a140 3 if ( (rfd = setup_device(radiofile, O_RDWR, &radio_term, &radio_save)) == ERROR ) exit( 1 ); d142 4 a145 1 if ( time(&start_time) == (time_t)ERROR ) d147 2 a148 2 fprintf( stderr, "Couldn't get time of day\n" ); exit( 1 ); d154 1 a154 1 exit( 1 ); d157 6 d164 1 a164 1 exit( 1 ); d166 1 a166 1 do d169 1 a169 1 break; d171 3 a173 1 } while( curtime < start_time + (60 *duration) ); d176 3 a179 7 ioctl( gfd, TCSETA, gps_save ); /* Restore GPS device */ close( gfd ); ioctl( rfd, TCSETA, radio_save ); /* Restore radio device */ close( rfd ); exit( 0 ); a200 26 /* Function : set_baud */ /* Purpose : Set baud rate into termio structure */ /* Inputs : termio pointer, baud rate */ /* Outputs : TRUE if OK, else FALSE */ /************************************************************************/ Boolean set_baud( struct termio *tp, Int baud ) { Int i; tp->c_cflag &= ~_CBAUD; for ( i = 0; i < (sizeof(bauds)/sizeof(struct baudstruct)); i++ ) if ( baud == bauds[i].ibaud ) { tp->c_cflag |= bauds[i].bflag; return( TRUE ); } fprintf( stderr, "Invalid baud rate: %d\n", baud ); return( FALSE ); } /* set_baud() */ /************************************************************************/ a253 36 /* Function : setup_device */ /* Purpose : Open a device file, set characteristics * /* Inputs : Device name, open mode, new termio characteristics, */ /* place to save old termio characteristics */ /* Outputs : none */ /************************************************************************/ Int setup_device( char *device, Int mode, struct termio *setup, struct termio *save ) { Int fd; /* File descriptor */ if ( (fd = open(device, mode)) < 0 ) { fprintf( stderr, "Could not open %s\n", device ); return( ERROR ); } if ( ioctl(fd, TCGETA, save) < 0 ) { fprintf( stderr, "TCGETA failed on %s\n", device ); return( ERROR ); } if ( ioctl(fd, TCSETA, setup) < 0 ) { fprintf( stderr, "TCSETA failed on %s\n", device ); return( ERROR ); } return( fd ); } /* setup_device() */ /************************************************************************/ d264 1 a264 1 Int childpid, fd; a265 8 if ( (childpid = fork()) < 0 ) /* Fork to detach terminal*/ { fprintf(stderr, "Can't fork child process\n"); return( FALSE ); } else if ( childpid > 0 ) /* Parent proecess exits */ exit( 0 ); d378 14 @