NCEPLIBS-bufr 11.7.1
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
18void prtusage( char * );
19
20#define MXFLEN 125
21
35void 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
110int 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 ...
subroutine bvers(CVERSTR)
This subroutine returns a character string containing the version number of the BUFRLIB software.
Definition: bvers.f:34
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:37
subroutine wrdlen
This subroutine figures out some important information about the local machine on which the BUFRLIB s...
Definition: wrdlen.F:36
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
void prtusage(char *)
This function prints program usage information to standard output.
Definition: xbfmg.c:35