head 1.1; access ; symbols ; locks oasisa:1.1; strict; comment @ * @; 1.1 date 2001.06.19.13.01.48; author oasisa; state Exp; branches ; next ; desc @ Periodic Update w/ changes to utils plus new utils 6/19/2001 (klh) @ 1.1 log @Initial revision @ text @/****************************************************************************/ /* Copyright 1994 MBARI */ /****************************************************************************/ /* $Header: decodeb.c,v 2.2 93/09/17 10:59:04 hebo Exp $ */ /* Summary : Program to decode an OASIS binary file */ /* Filename : decodeb.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 2.2 $ */ /* Created : 01/04/94 */ /* */ /* MBARI provides this documentation and code "as is", with no warranty, */ /* express or implied, of its quality or consistency. It is provided without*/ /* support and without obligation on the part of the Monterey Bay Aquarium */ /* Research Institute to assist in its use, correction, modification, or */ /* enhancement. This information should not be published or distributed to */ /* third parties without specific written permission from MBARI. */ /* */ /****************************************************************************/ /* Modification History: */ /* 04jan94 rah - created */ /****************************************************************************/ #include /* Standard I/O */ #include /* For exit() */ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* Time */ #include /* for memcpy() */ #include /* for isspace() */ #include /* for strcmp() */ #define UUBUFSIZE 512 /* Size of uu decode buffer */ #define BUFSIZE 2048 /* Size of sample buffer */ #define NAMESIZE 256 /* Space allocated for file names */ #define UUERROR (-2) /* Error return from uuread() */ #define ANALOG_CHANS 8 /* Number of analog channels */ #define PAR_CHAN 0 /* Analog channel number for PARs */ #define OASIS_CHAN 2 /* Analog chan num for OASIS stuff */ #define DEC(c) (((c) - ' ') & 0x3f) /* uudecode macro */ /********************************/ /* 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 Byte buffer[BUFSIZE]; /* Decoded data buffer */ MLocal Byte uubuf[UUBUFSIZE]; /* Buffer for raw uuencoded data */ MLocal LogRecHdr hdr; /* Logging record header */ MLocal time_t oasis_time; /* Time of OASIS data in time_t fmt */ MLocal MBool dolocaltime = TRUE; /* Output local (not GMT) time */ MLocal MBool donumber = FALSE; /* Output log numbers */ MLocal char tmp_buf[NAMESIZE]; /* Misc temporary buffer */ MLocal MBool decode_all = TRUE; /* Decode all sensors */ MLocal MBool decode_sensor[SENSORS]; /* TRUE to decode particular sensor */ /* File names */ MLocal char *cfgp = NULL; /* Ptr to name of OASIS config file */ MLocal char cfg_file[NAMESIZE]; /* Name of OASIS configuration file */ MLocal char atlas_file[NAMESIZE]; /* Name of ATLAS calibration file */ MLocal char ctd_file[NAMESIZE]; /* Name of CTD calibration file */ MLocal char spec_file[NAMESIZE]; /* Name of Spectro calibration file */ MLocal char *sensor_names[] = { "Empty", "Time", "ATLAS", "OASIS", "PAR", "CTD", "Spectro", "ADCP", "GPS", "Modem", "pCO2", "CTD2", "CTD3", "Spectro10", "Spectro20", "Nitrate", "Nitrate2", "SpecPRR", "Satlantic", "GPS", "NRL", "Oxygen", "Fluorometer", "Transmissometer", "NO3", "NO3.2", "AC9", "CO2Pump", "H2OPump", "Shutter0", "Shutter1" }; /********************************/ /* Forward Declarations */ /********************************/ MBool process_command_line ( Int argc, char **argv ); Void use_msg( char *s ); Void decode_file( char *s ); Status read_cfg( char **cfgname, char *dataname ); Int32 get_begin_line( FILE *fd ); FILE *uuopen( char *name ); Int uuread( Byte *buf, Int len, FILE *fd ); Int uugetline( Byte *buf, Int len, FILE *fd ); Nat16 getIntelword( Byte *p ); Nat32 getIntellong( Byte *p ); Void print_header( char *ident ); Void printbytes( Byte *s, Int len ); Void print_ascii( Int len, MBool strip_nl ); Void print_error( Status err ); /************************************************************************/ /* Function : main */ /* Purpose : Main routine */ /* Inputs : argc, argv */ /* Outputs : none */ /************************************************************************/ Void main( Int argc, char **argv ) { Int i; char *filename, *cp; if ( !process_command_line(argc, argv) ) { use_msg(argv[0]); exit( 1 ); } for ( i = optind; i < argc; i++ ) { filename = argv[i]; cp = cfgp; if ( read_cfg(&cp, filename) != OK ) printf("Can't read configuration file \"%s\"\n", cp); else decode_file( filename ); } exit( 0 ); } /* main() */ /************************************************************************/ /* Function : decode_file */ /* Purpose : Decode one data file, print results to stdout */ /* Inputs : File name */ /* Outputs : none */ /************************************************************************/ Void decode_file( char *filename ) { Int cc, len, len_got; FILE *fd; struct tm *tp; MBool did_err_msg; Status rtn; if ( (fd = uuopen(filename)) == (FILE *)NULL ) return; if( get_begin_line(fd) < 0 ) { printf("No begin line in %s\n", filename); return; } did_err_msg = FALSE; while ( (cc = uugetline(buffer, sizeof(buffer), fd)) != EOF ) { if ( cc == UUEND ) { if( get_begin_line(fd) < 0 ) break; else continue; } if ( cc == 0 ) continue; did_err_msg = FALSE; hdr.log_type = buffer[0]; hdr.log_nmbr = getIntelword(&buffer[1]); hdr.log_len = getIntelword(&buffer[3]); hdr.log_time = getIntellong(&buffer[5]); len_got = cc - 9; /* compute amount of log data gotten*/ memmove( buffer, buffer + 9, sizeof(buffer) - 9 ); /* Move log data to start of buffer*/ if ( (len = hdr.log_len) > sizeof(buffer) ) { /* Get size of log data */ len = sizeof(buffer); printf("Record too long in %s. Truncating.\n", filename); } if ( len_got < len ) { if ( (len_got += uuread(buffer+len_got, len-len_got, fd)) != len) { if ( !did_err_msg ) printf("Bad record in %s\n", filename); did_err_msg = TRUE; continue; } did_err_msg = FALSE; } if ( !decode_all && !((hdr.log_type < SENSORS) && decode_sensor[hdr.log_type]) ) continue; if ( hdr.log_type < SENSORS ) { print_header( sensor_names[hdr.log_type] ); printbytes(buffer, len); } else if ( hdr.log_type == LOG_ERROR ) { cc = getIntelword(buffer); if ( cc & 0x8000 ) { cc &= 0x7fff; print_header("OASIS Error"); if ( cc & RAM_ERR ) printf("RAM_init "); if ( cc & LOG_ERR ) printf("LOG_memory_bad "); if ( cc & CLOCK_ERR ) printf("Clock_failure "); if ( cc & INT_ERR ) printf("Spurious_interrupt "); if ( cc & RESTART_ERR ) printf("Restarted "); if ( cc & COMM_ERR ) printf("24hr_silence"); printf("\n"); } else { if ( cc >= SENSORS ) printf("Unknown Error type\n"); else { printf( sensor_names[cc] ); print_header( " Error" ); printf("\n"); } } } else { print_header("Unknown record type"); printf("\n"); } } fclose( fd ); } /* decode_file() */ /************************************************************************/ /* Function : use_msg */ /* Purpose : Print Usage Message */ /* Inputs : Name of program */ /* Outputs : None */ /************************************************************************/ Void use_msg( char *s ) { fprintf( stderr, "Usage: %s [-c cfg_file] [-i instrument] [-g] [-l] [-n]", s ); } /* 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; for ( i = 0; i < SENSORS; i++ ) decode_sensor[i] = FALSE; while ( (i = getopt(argc, argv, "c:gi:ln")) != EOF ) switch( i ) { case 'c': cfgp = optarg; break; case 'g': dolocaltime = FALSE; break; case 'i': for ( i = 0; i < SENSORS; i++ ) if ( strcmp(optarg, sensor_names[i]) == 0 ) { decode_all = FALSE; decode_sensor[i] = TRUE; } break; case 'l': dolocaltime = TRUE; break; case 'n': donumber = TRUE; break; default: return( FALSE ); } return( TRUE ); } /* process_command_line() */ /************************************************************************/ /* Function : get_begin_line */ /* Purpose : Look for "begin" line in uuencode file */ /* Inputs : FILE pointer */ /* Outputs : Log number n from "begin 644 oasis.n". */ /************************************************************************/ Int32 get_begin_line( FILE *fd ) { Int32 unused, lognum; while ( fgets((char *)uubuf, sizeof(uubuf), fd) != NULL ) { if ( sscanf((char *)uubuf, " begin %d oasis.%d", &unused, &lognum) >= 2) return( lognum ); } return( ERROR ); } /* get_begin_line() */ /************************************************************************/ /* Function : uuopen */ /* Purpose : Open a uuencoded file, check its "begin" line */ /* Inputs : Name of file */ /* Outputs : FILE pointer */ /************************************************************************/ FILE *uuopen( char *name ) { FILE *fd; if ( (fd = fopen(name, "rb")) == (FILE *)NULL ) printf("Cannot open %s\n", name); return( fd ); } /* uuopen() */ /************************************************************************/ /* Function : uudecode */ /* Purpose : Decode a group of 3 binary bytes from 4 input characters*/ /* Inputs : Ptr to input chars, ptr to output, number of bytes */ /* Outputs : None */ /************************************************************************/ Void uudecode( Byte *in, Byte *out, Int len ) { Byte *p; p =out; if ( len >= 1 ) *p++ = (DEC(*in) << 2) | (DEC(in[1]) >> 4); if ( len >= 2 ) *p++ = (DEC(in[1]) << 4) | (DEC(in[2]) >> 2); if ( len >= 3 ) *p = (DEC(in[2]) << 6) | (DEC(in[3])); } /* uudecode() */ /************************************************************************/ /* Function : uugetline */ /* Purpose : Read and decode one line from a uuencoded file */ /* Inputs : Buffer for resulting data, size of buffer, FILE ptr */ /* Outputs : Number characters read, UUERROR if error, or EOF */ /************************************************************************/ Int uugetline( Byte *buf, Int len, FILE *fd ) { Int uulen, i; Byte *p, *q; char *p1; if ( fgets((char *)uubuf, sizeof(uubuf), fd) == NULL ) return( EOF ); if (strncmp((char *)uubuf, "end", 3) == 0) return( UUEND ); uulen = DEC(uubuf[0]); if ( (p1 = strchr((char *)uubuf, '\n')) != NULL ) *p1 = '\0'; if ( (p1 = strchr((char *)uubuf, '\r')) != NULL ) *p1 = '\0'; if ( strlen((char *)uubuf) != (((uulen + 2)/3 * 4) + 1) ) return( UUERROR ); p = &uubuf[1]; q = buf; for ( i = uulen; i > 0; i -= 3 ) { uudecode( p, q, i ); p += 4; q += 3; } return( uulen ); } /* uugetline() */ /************************************************************************/ /* Function : uuread */ /* Purpose : Read and decode len bytes from a uuencoded file */ /* Inputs : Buffer for resulting data, size of buffer, FILE ptr */ /* Outputs : Number characters read, UUERROR if error, or EOF */ /* Comment : OASIS records should always begin and end at new line */ /* This function calls uugetline() for the appropriate */ /* number of bytes, and returns UUERROR if size wrong */ /************************************************************************/ Int uuread( Byte *buf, Int len, FILE *fd ) { Int i, left; Byte *p; for ( p = buf, left = len; left > 0; ) { if ( (i = uugetline(p, left, fd)) <= 0 ) return( i ); left -= i; p += i; if ( left < 0 ) return( UUERROR ); } return( len ); } /* uuread() */ /************************************************************************/ /* Function : getIntelword */ /* Purpose : Get a word in Intel format from data stream */ /* Inputs : Ptr to data stream */ /* Outputs : Word */ /************************************************************************/ Nat16 getIntelword( Byte *p ) { Nat16 rtn; rtn = (Nat16)(*p); rtn += (Nat16)(p[1] << 8); return( rtn ); } /* getIntelword() */ /************************************************************************/ /* Function : getIntellong */ /* Purpose : Get a longword in Intel format from data stream */ /* Inputs : Ptr to data stream */ /* Outputs : Long */ /************************************************************************/ Nat32 getIntellong( Byte *p ) { Nat32 rtn; rtn = (Nat32)getIntelword(p); rtn += ((Nat32)getIntelword(&p[2]) << 16); return( rtn ); } /* getIntellong() */ /************************************************************************/ /* Function : getMotword */ /* Purpose : Get a word in Motorola format from data stream */ /* Inputs : Ptr to data stream */ /* Outputs : Word */ /************************************************************************/ Nat16 getMotword( Byte *p ) { Nat32 rtn; rtn = (Nat16)(*p << 8); rtn += (Nat16)(p[1]); return( rtn ); } /* getMotword() */ /************************************************************************/ /* Function : print_header */ /* Purpose : Print log header */ /* Inputs : Identification string */ /* Outputs : None */ /************************************************************************/ Void print_header( char *ident ) { struct tm *tp; if ( dolocaltime ) tp = localtime( (time_t *)&hdr.log_time ); else tp = gmtime( (time_t *)&hdr.log_time ); printf( "%-8s ", ident ); if ( donumber ) printf("%4d ", hdr.log_nmbr); printf("%02d/%02d/%02d %02d:%02d:%02d ", tp->tm_year, tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); } /* print_header() */ /************************************************************************/ /* Function : printbytes */ /* Purpose : Print data stream as a stream of bytes */ /* Inputs : Byte ptr, length */ /* Outputs : None */ /************************************************************************/ Void printbytes( Byte *s, Int len ) { Int i, curlen; for ( i = 0; i < len; ) { printf("\n "); curlen = len - i; if ( curlen > 32 ) curlen = 32; while ( curlen-- ) printf("%02x", s[i++]); } printf("\n"); } /* printbytes() */ /************************************************************************/ /* Function : print_ascii */ /* Purpose : Print data stream as ascii stream */ /* Inputs : Length, MBool to strip CR & LF */ /* Outputs : None */ /************************************************************************/ Void print_ascii( Int len, MBool strip_nl ) { char *p; buffer[len] = '\0'; if ( strip_nl ) { while ( (p = strchr((char *)buffer, '\r')) != NULL ) *p = ' '; while ( (p = strchr((char *)buffer, '\n')) != NULL ) *p = ' '; } printf("%s\n", buffer); } /* print_ascii() */ /************************************************************************/ /* Function : print_error */ /* Purpose : Print error in decoding data */ /* Inputs : Error type */ /* Outputs : None */ /************************************************************************/ Void print_error( Status err ) { switch( err ) { case ERROR: printf("Error\n"); break; case SIZE_ERR: printf("Wrong size\n"); break; case CHKSUM_ERR: printf("Checksum error\n"); break; case FMT_ERR: printf("Bad data format\n"); break; default: printf("Unknown error\n"); } } /* print_error() */ /************************************************************************/ /* Function : read_cfg */ /* Purpose : Read OASIS configuration file */ /* Inputs : Ptr to cfg file name ptr, name of data file */ /* Outputs : OK or ERROR */ /* Comments : If *cfgname (user-passed cfg file) is NULL, looks at */ /* data file name to attempt correct configuration */ /* If that fails, default cfg file is for m1a */ /************************************************************************/ Status read_cfg( char **cfgname, char *dataname ) { return( OK ); } /* read_cfg() */ @