NCEPLIBS-bufr  11.7.0
 All Data Structures Files Functions Variables Pages
xbfmg.c
Go to the documentation of this file.
1 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <libgen.h>
9 #include <unistd.h>
10 #include <sys/stat.h>
11 
12 #include "bufrlib.h"
13 
14 #ifdef UNDERSCORE
15 #define prtusage prtusage_
16 #endif
17 
18 void prtusage( char * );
19 
20 #define MXFLEN 125
21 
35 void prtusage( char *prgnam ) {
36  printf( "\nUSAGE: %s [-v] [-h] [-g] bufrfile\n\n", prgnam );
37  printf( "WHERE:\n" );
38  printf( " -v prints program version information and exits\n" );
39  printf( " -h prints program help and usage information and exits\n" );
40  printf( " -g preserves within each output file any GTS bulletin header and\n" );
41  printf( " control characters associated with the corresponding BUFR message\n" );
42  printf( " from the input file\n" );
43  printf( " bufrfile [path/]name of input file containing one or more BUFR messages\n" );
44  printf( " to be extracted into separate output files within the current\n" );
45  printf( " working directory\n\n" );
46  printf( "The output will be stored within the current working directory using the\n" );
47  printf( "following filenames:\n\n" );
48  printf( " (basename).xbfmg.out.000001\n" );
49  printf( " (basename).xbfmg.out.000002\n" );
50  printf( " (basename).xbfmg.out.000003\n" );
51  printf( " .\n" );
52  printf( " .\n" );
53  printf( " (basename).xbfmg.out.(last#)\n\n" );
54  printf( "where:\n\n" );
55  printf( " (basename) = basename of bufrfile\n" );
56  printf( " (last#) = total number of BUFR messages in bufrfile\n\n" );
57 }
58 
110 int main( int argc, char *argv[] ) {
111 
112  struct stat fileinfo;
113 
114  char *pc, *pmsg, *psb;
115 
116  int save_GTSbull = 0;
117 
118  char outfile[MXFLEN];
119  char outfile_temp[MXFLEN];
120  char wkstr[MXFLEN];
121 
122  char *bvstr;
123 
124  int ch;
125 
126  FILE *fp;
127 
128  f77int msglen, wkint;
129  f77int c24 = 24, c1 = 1;
130 
131  unsigned long i, filesize, noutfile;
132 
133  unsigned short ii;
134 
135  /*
136  ** Get the valid options from the command line:
137  */
138  while ( ( ch = getopt ( argc, argv, "vgh" ) ) != EOF ) {
139  switch ( ch ) {
140  case 'v':
141  bvstr = ( char * ) calloc( 9, sizeof(char) ); /* allocate bvstr and initialize to all nulls */
142  bvers( bvstr, sizeof(bvstr) );
143  printf( "This is xbfmg v3.2.0, built with BUFRLIB v%s\n", bvstr );
144  return 0;
145  case 'g':
146  save_GTSbull = 1;
147  break;
148  case 'h':
149  printf( "\nPROGRAM %s\n", argv[0] );
150  printf( "\nABSTRACT: This program reads an input file containing one or more\n" );
151  printf( " BUFR messages as given by the first argument. It then extracts each\n" );
152  printf( " each individual BUFR message into its own separate output file within\n" );
153  printf( " the current working directory.\n" );
154  prtusage( argv[0] );
155  return 0;
156  break;
157  }
158  }
159 
160  /*
161  ** There should be one remaining command line argument specifying the input file.
162  */
163  if ( (optind+1) != argc ) {
164  printf( "\nERROR: You must specify an input BUFR file of BUFR messages!\n" );
165  prtusage( argv[0] );
166  return -1;
167  }
168 
169  /*
170  ** Get the filesize of the input file.
171  */
172  if ( stat( argv[optind], &fileinfo ) != 0 ) {
173  printf( "\nERROR: Could not stat the file %s!\n", argv[optind] );
174  return -1;
175  }
176  filesize = fileinfo.st_size;
177 
178  /*
179  ** Dynamically allocate memory in order to read in the input file.
180  */
181  if ( ( pc = malloc( filesize + 1 ) ) == NULL ) {
182  printf( "\nERROR: Could not allocate memory for file %s!\n", argv[optind] );
183  return -1;
184  }
185 
186  /*
187  ** Read the input file into memory.
188  */
189  if ( ( fp = fopen( argv[optind], "rb" ) ) == NULL ) {
190  printf( "\nERROR: Could not open input file %s!\n", argv[optind] );
191  return -1;
192  }
193  for ( i = 0; i < filesize; i++ ) {
194  pc[i] = (char) fgetc( fp );
195  }
196  pc[i] = '\0';
197  fclose( fp );
198 
199  /*
200  ** Create an output file name template.
201  */
202  strcpy( wkstr, argv[optind] );
203  strcpy( outfile_temp, basename( wkstr ) );
204  strcat( outfile_temp, ".xbfmg.out" );
205 
206  /*
207  ** Call wrdlen function to initialize BUFRLIB and determine machine endianness.
208  */
209  wrdlen( );
210 
211  /*
212  ** Locate each BUFR message within the input file and write each one to a separate output file.
213  **
214  ** Note that we can't use the intrinsic C strstr function to locate the "BUFR" and "7777"
215  ** strings within the file, because the file could contain embedded NULL characters.
216  */
217  noutfile = 0;
218  pmsg = psb = pc;
219  while ( 1 ) {
220  while ( ( ( pmsg - pc + 4 ) < filesize ) &&
221  ( ( *(pmsg) != 'B' ) ||
222  ( *(pmsg + 1) != 'U' ) ||
223  ( *(pmsg + 2) != 'F' ) ||
224  ( *(pmsg + 3) != 'R' ) ) ) {
225  if ( *pmsg == '\x01' ) psb = pmsg;
226  pmsg++;
227  }
228  if ( ( pmsg - pc + 4 ) >= filesize ) {
229  free( pc );
230  return 0;
231  }
232 
233  /*
234  ** Open a new output file for this message.
235  */
236  sprintf( outfile, "%s.%06lu", outfile_temp, ++noutfile );
237  if ( ( fp = fopen( outfile, "wb" ) ) == NULL ) {
238  printf( "\nERROR: Could not open output file %s!\n", outfile );
239  return -1;
240  }
241 
242  /*
243  ** If requested, write the preceding GTS bulletin information to the output file.
244  */
245  if ( save_GTSbull ) {
246  while ( psb < pmsg ) {
247  fputc( *psb++, fp );
248  }
249  }
250 
251  /*
252  ** Read the BUFR message length from Section 0.
253  */
254  memcpy( &wkint, ( pmsg + 4 ), 3 );
255  msglen = iupb( &wkint, &c1, &c24 );
256 
257  /*
258  ** Write the BUFR message to the output file.
259  */
260  if ( ( pmsg + msglen - pc - 1 ) <= filesize ) {
261  for ( i = 1; i <= msglen; i++ ) {
262  fputc( *pmsg++, fp );
263  }
264  }
265 
266  /*
267  ** Make sure that the "7777" indicator is in the expected place.
268  */
269  if ( ( *(pmsg - 4) != '7' ) || ( *(pmsg - 3) != '7' ) ||
270  ( *(pmsg - 2) != '7' ) || ( *(pmsg - 1) != '7' ) ) {
271  printf( "\nERROR: Could not find 7777 indicator in output file %s!\n",
272  outfile );
273  }
274 
275  /*
276  ** If requested, append GTS bulletin tail markers to the output file.
277  */
278  if ( save_GTSbull ) {
279  fputc( '\x0d', fp );
280  fputc( '\x0d', fp );
281  fputc( '\x0a', fp );
282  fputc( '\x03', fp );
283  }
284 
285  fclose( fp );
286  }
287 }
Define signatures to enable a number of BUFRLIB subprograms to be called directly from C application ...
function iupb(MBAY, NBYT, NBIT)
THIS FUNCTION UNPACKS AND RETURNS A BINARY INTEGER WORD CONTAINED WITHIN NBIT BITS OF A BUFR MESSAGE ...
Definition: iupb.f:36
subroutine bvers(CVERSTR)
This subroutine returns a character string containing the version number of the BUFRLIB software...
Definition: bvers.f:33
void prtusage(char *)
This function prints program usage information to standard output.
Definition: xbfmg.c:35
subroutine wrdlen
This subroutine figures out some important information about the local machine on which the BUFRLIB s...
Definition: wrdlen.F:35
int main(int argc, char *argv[])
This program splits a single file containing one or more BUFR messages into one or more BUFR files ea...
Definition: xbfmg.c:110