nmxptool_getoptlong.c 45.4 KB
Newer Older
Matteo Quintiliani's avatar
Matteo Quintiliani committed
1 2 3 4 5 6 7 8 9
/*! \file
 *
 * \brief Nanometrics Protocol Tool
 *
 * Author:
 * 	Matteo Quintiliani
 * 	Istituto Nazionale di Geofisica e Vulcanologia - Italy
 *	quintiliani@ingv.it
 *
10
 * $Id: nmxptool_getoptlong.c,v 1.125 2010-09-15 13:14:49 mtheo Exp $
Matteo Quintiliani's avatar
Matteo Quintiliani committed
11 12 13
 *
 */

14 15 16 17
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

18 19 20
#include <errno.h>
#include <unistd.h>

21 22 23 24 25
#include "config.h"
#include "nmxp.h"

#include "nmxptool_getoptlong.h"

26
const NMXPTOOL_PARAMS NMXPTOOL_PARAMS_DEFAULT =
27 28
{
    NULL,
29 30
    DEFAULT_PORT_DAP,
    DEFAULT_PORT_PDS,
31 32 33
    NULL,
    NULL,
    NULL,
34 35
    0.0,
    0.0,
36
    DEFAULT_INTERVAL_NO_VALUE,
37 38
    NULL,
    NULL,
39 40
    DEFAULT_STC,
    DEFAULT_RATE,
41
    NULL,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
42
    DEFAULT_DELAY,
43
    DEFAULT_SPANINTERVAL,
44 45
    DEFAULT_MAX_TOLERABLE_LATENCY,
    DEFAULT_TIMEOUTRECV,
46
    DEFAULT_VERBOSE_LEVEL,
47
    NULL,
48
    NULL,
49
    NULL,
50
    DEFAULT_TYPE_WRITESEED,
51
    DEFAULT_BUFFERED_TIME,
52
    DEFAULT_N_CHANNEL,
53
    DEFAULT_USEC,
54
    DEFAULT_MAX_TIME_TO_RETRIEVE,
55
    DEFAULT_NETWORKDELAY,
56
    DEFAULT_LISTEN_PORT,
57
    DEFAULT_TIMING_QUALITY,
58 59
    DEFAULT_QUALITY_INDICATOR,
    DEFAULT_ENCODING,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
60
    DEFAULT_RECLEN_MINISEED,
61
    0,
62 63 64 65
    0,
    0,
    0,
    0,
66
    0,
67
    0,
68
    0,
69 70 71
    0
};

72 73

void nmxptool_author_support() {
74
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
75 76
Matteo Quintiliani - Istituto Nazionale di Geofisica e Vulcanologia - Italy\n\
Mail bug reports and suggestions to <%s>.\n",
77
	    NMXP_LOG_STR(PACKAGE_BUGREPORT)
78 79 80 81
	    );
}


Matteo Quintiliani's avatar
Matteo Quintiliani committed
82 83 84
#define PDS_VERSION "1.4"
#define DAP_VERSION "1.0"

85
void nmxptool_version() {
86
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
87
%s %s, tool for Nanometrics Protocols\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
88 89 90
         Private Data Stream %s, Data Access Protocol %s\n",
	NMXP_LOG_STR(PACKAGE_NAME), NMXP_LOG_STR(PACKAGE_VERSION),
	NMXP_LOG_STR(PDS_VERSION), NMXP_LOG_STR(DAP_VERSION)
91
	/*
92
	nmxp_log_version()
93
	*/
94
	    );
Matteo Quintiliani's avatar
Matteo Quintiliani committed
95 96

    nmxptool_supports();
97 98
}

99

Matteo Quintiliani's avatar
Matteo Quintiliani committed
100
void nmxptool_supports() {
101
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
102
         Enabled features: libmseed ");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
103
#ifdef HAVE_LIBMSEED
104
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "YES");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
105
#else
106
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "NO");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
107 108
#endif

109
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ", SeedLink ");
110
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
111
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "YES");
112
#else
113
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "NO");
114 115
#endif

116
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ", Earthworm ");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
117
#ifdef HAVE_EARTHWORMOBJS
118
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "YES");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
119
#else
120
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "NO");
121 122 123 124 125 126 127 128 129
#endif
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ".\n");

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
         Using pthread: ");
#ifdef HAVE_PTHREAD_H
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "YES");
#else
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "NO");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
130
#endif
131 132 133 134 135

#ifdef NMXP_MEM_DEBUG
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ". Enabled memdebug");
#endif

136
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ".\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
137 138
}

139

140 141
void nmxptool_usage(struct option long_options[])
{
142
    nmxptool_version();
Matteo Quintiliani's avatar
Matteo Quintiliani committed
143

144
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
145
\n\
146
Usage: %s -H hostname  [  -C channellist ]  -l | -L \n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
147
             Print list of the available Time Series channels\n\
148
             on DataServer and NaqsServer respectively.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
149 150 151 152
\n",
NMXP_LOG_STR(PACKAGE_NAME));

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
153
       %s -H hostname -C channellist [...]\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
154
             Receive data in near real-time from NaqsServer by PDS %s\n\
155
\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
156
       %s -H hostname -F statefile [-A SECs] [...]\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
157 158
             Receive data from NaqsServer and, in case, retrieve previous\n\
             data from DataServer up to SECs seconds before.\n\
159 160
\n",
NMXP_LOG_STR(PACKAGE_NAME),
Matteo Quintiliani's avatar
Matteo Quintiliani committed
161 162 163 164 165 166 167 168
NMXP_LOG_STR(PDS_VERSION),
NMXP_LOG_STR(PACKAGE_NAME));

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
       %s -H hostname -C channellist -s DATE -e DATE [...]\n\
       %s -H hostname -C channellist -s DATE -t TIME [...]\n\
             Receive a temporal interval of data from DataServer by DAP %s\n\
\n",
169 170
NMXP_LOG_STR(PACKAGE_NAME),
NMXP_LOG_STR(PACKAGE_NAME),
Matteo Quintiliani's avatar
Matteo Quintiliani committed
171 172
NMXP_LOG_STR(DAP_VERSION)
);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
173 174

#ifdef HAVE_EARTHWORMOBJS
175
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
176
       %s nmxptool.d\n\
177
             Launched as Earthworm module to redirect data into the EW-Rings.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
178
             Refer to nmxptool_cmd.html into the Earthworm documentation.\n\
179
\n", NMXP_LOG_STR(PACKAGE_NAME));
180 181 182 183
#endif

#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
184
       %s <option ... option> [ -k  |  -K ]\n\
185
             Launched as SeedLink plug-in to feed the SL-Server.\n\
186
\n", NMXP_LOG_STR(PACKAGE_NAME));
Matteo Quintiliani's avatar
Matteo Quintiliani committed
187 188
#endif

189
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
190
       %s --help | -h\n\
191
             Print this help.\n\
192
\n", NMXP_LOG_STR(PACKAGE_NAME));
193 194

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
195
Main arguments:\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
196
  -H, --hostname=HOST     NaqsServer/DataServer hostname or IP address.\n\
197
  -C, --channels=LIST     List of NET.STA.CHAN.LOC separated by comma.\n\
198
                          NET  is optional and used only for output.\n\
199 200
                          STA  can be '*', it stands for all stations.\n\
                          CHAN can contain '?', it stands for any character.\n\
201 202 203
                          LOC  is optional and used only for output.\n\
                          Network and location code will be assigned from the\n\
                          first pattern that include station and channel.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
204
                          DO NOT USE with -F.\n\
205
                                Example: N1.AAA.HH?.01,N2.*.HH?,MMM.BH?.03\n\
206 207
                          Second pattern includes the first. Unless AAA, all\n\
                          stations with HH channels will have network to N2.\n\
208
                          Stations N2.*.HH? will have default location defined by -n.\n\
209
                          Station MMM will have default network defined by -N.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
210
  -F, --statefile=FILE    List of channel patterns, as in -C. One for each line.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
211 212 213
                          Load/Save time of the last sample of each channel\n\
                          into a file with the same name, same directory,\n\
                          appending the suffix '%s'.\n\
214 215
                          It enables the option -b in order to allow data continuity\n\
                          when short disconnections occur or between program restarts.\n\
216
                          Related to -L, -A and -f. DO NOT USE with -C.\n",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
217 218
			  NMXP_STR_STATE_EXT
);
219 220

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
221
  -A, --maxdataretr=SECs  Max amount of data of the past to retrieve from the\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
222
                          DataServer when program restarts (default %d) [%d..%d].\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
223 224 225
                          0 to disable connection to DataServer.\n\
                          If this option is equal to zero and -F is used,\n\
                          only data buffered by NaqsServer will be retrieved.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
226 227 228
                          Rather than using -A, it is preferable, inside the section\n\
                          Datastream of the file Naqs.ini, setting DataBufferLength \n\
                          to a high value. -A allows to retrieve much more\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
229
                          data of the past when the program restarts but it\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
230
                          considerably slows down the execution.\n\
231 232 233
                          It is extremely harmful when you have many channels,\n\
                          in this case you might consider to subdivide the\n\
                          channels into different nmxptool instances.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
234
                          Related to -F.\n\
235 236 237 238 239 240 241
\n",
	    DEFAULT_MAX_TIME_TO_RETRIEVE,
	    DEFAULT_MAX_TIME_TO_RETRIEVE_MINIMUM,
	    DEFAULT_MAX_TIME_TO_RETRIEVE_MAXIMUM
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
242 243
PDS arguments for NaqsServer:\n\
  -P, --portpds=PORT      NaqsServer port number (default %d).\n\
244 245
  -S, --stc=SECs          Short-Term-Completion (default %d).\n\
                          -1 is for Raw Stream, no Short-Term-Completion.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
246
                             Packets contain compressed data. Related to -M, -T.\n\
247 248
                             It enables --rate=-1.\n\
                           0 decompressed packets are received in chronological\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
249
                             order without waiting for missing packets.\n\
250
                          [1..300] decompressed packets are received in\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
251
                             chronological order but waiting for missing packets\n\
252
                             at most SECs seconds.\n\
253 254 255 256 257
  -R, --rate=Hz           Receive data with specified sample rate (default %d).\n\
                          -1 for original sample rate and compressed data.\n\
                           0 for original sample rate and decompressed data.\n\
                          >0 for specified sample rate and decompressed data.\n\
  -b, --buffered          Request also recent packets into the past.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
258
  -B, --buffdate=DATE     Request also recent packets into the past\n\
259
                          but consider only samples after DATE.\n",
260 261 262 263 264
	    DEFAULT_PORT_PDS,
	    DEFAULT_STC,
	    DEFAULT_RATE);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
265
  -f, --mschan=mSECs/nC   mSECs are milliseconds to wait before the next request,\n\
266
                          nC is the number of channels to request at a time.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
267
                          Delaying and requesting few channels at a time make\n\
268 269
                          data buffering on NaqsServer side more efficient.\n\
                          Determined empiric values are default %d/%d.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
270
                          Condition: TotalNumberOfChannels * (mSECs/nC) < %d sec. \n\
271
                          Related to -F and -b. 0/0 for disabling.\
272
\n",
273
DEFAULT_USEC / 1000, DEFAULT_N_CHANNEL, NMXP_MAX_MSCHAN_MSEC / 1000);
274 275

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
276
  -L, --listchannelsnaqs  List of the available Time Series channels on NaqsServer.\n\
277 278
                          The output list of channels can be redirected to a file\n\
                          which can be used as an input statefile for the option -F.\n\
279
  -M, --maxlatency=SECs   Max tolerable latency (default %d) [%d..%d].\n\
280 281 282 283
                          Enable NaqsServer to send out retransmission requests\n\
                          for missed packets. Inside the section NetworkInterface\n\
                          of the file Naqs.ini set RetxRequest to Enabled.\n\
                          If RetxRequest is not enabled then -M is ineffective.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
284
  -T, --timeoutrecv=SECs  Time-out for flushing queued packets of each channel.\n\
285
                          It sets --mschan=0/0 (default %d, no time-out) [%d..%d].\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
286
                          -T is useful for retrieving Data On Demand with minimum delay.\n\
287
                          -M, -T are usable only with Raw Stream, -S=-1.\n\
288
                          In general, -M and -T are not used together.\n\
289
                          Receiving signals interrupts the time out.\n\
290 291 292 293 294 295 296 297 298 299 300
\n\
",
	    DEFAULT_MAX_TOLERABLE_LATENCY,
	    DEFAULT_MAX_TOLERABLE_LATENCY_MINIMUM,
	    DEFAULT_MAX_TOLERABLE_LATENCY_MAXIMUM,
	    DEFAULT_TIMEOUTRECV,
	    DEFAULT_TIMEOUTRECV_MINIMUM,
	    DEFAULT_TIMEOUTRECV_MAXIMUM
	  );

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
301
DAP arguments for DataServer:\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
302
  -D, --portdap=PORT      DataServer port number (default %d).\n\
303 304 305 306 307 308 309
  -s, --start_time=DATE   Start time in date format.\n\
  -e, --end_time=DATE     End time in date format.\n\
                          DATE can be in formats:\n\
                              <date>,<time> | <date>\n\
                          where:\n\
                              <date> = yyyy/mm/dd | yyy.jjj\n\
                              <time> = hh:mm:ss | hh:mm:ss.dddd | hh:mm\n\
310 311 312
  -t, --interval=TIME     Time interval from start_time (greater than zero).\n\
                          TIME is in seconds, otherwise append 'm' for minutes\n\
                          'h' for hours or 'd' for days. [1 sec .. %d days]\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
313
                          DO NOT USE with -e.\n\
314 315 316 317
  -d, --delay=TIME        Receive continuosly data with a fixed delay [%d sec .. %d days].\n\
  -a, --span_data=TIME    How much data is requested every time when receiving\n\
                          with a fixed delay [%d sec .. %d days]. (default %ds).\n\
                          Condition: span_data < delay - %ds. Related to -d.\n\
318 319
  -u, --username=USER     DataServer username.\n\
  -p, --password=PASS     DataServer password.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
320
  -l, --listchannels      List of the available Time Series channels on DataServer.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
321
  -i, --channelinfo       Print channelinfo (network name) when using -l.\n\
322 323
\n\
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
324
DEFAULT_PORT_DAP,
325
(DEFAULT_INTERVAL_MAXIMUM / 86400),
326
DEFAULT_DELAY_MINIMUM,
327 328 329 330 331 332
(DEFAULT_DELAY_MAXIMUM / 86400),
DEFAULT_SPANINTERVAL_MINIMUM,
(DEFAULT_SPANINTERVAL_MAXIMUM / 86400),
DEFAULT_SPANINTERVAL,
NMXP_DAP_TIMEOUT_KEEPALIVE
    );
333

334
#ifdef HAVE_LIBMSEED
335
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
336
Mini-SEED arguments:\n");
337

338
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
339 340 341
  -m, --writeseed=[TYPE]  Pack received data in Mini-SEED records and\n\
                          store them within a SDS or BUD structure.\n\
                          TYPE can be '%c' or '%c' (-m%c or -m%c)\n\
342
                          Packets are appended to existing files. Related to -o.\n",
343 344
			  TYPE_WRITESEED_SDS, TYPE_WRITESEED_BUD,
			  TYPE_WRITESEED_SDS, TYPE_WRITESEED_BUD);
345
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
346
  -o, --outdirseed=DIR    Output directory for SDS or BUD structure.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
347
                          Related to -m (default is current directory).\n");
348
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
349 350 351 352 353
  -q, --quality_indicator=IND\n\
                          Set the quality indicator to the given character.\n\
                          Seed 2.4 supports D (indeterminate), R (raw data),\n\
                          Q (quality controlled data) and M (data center modified).\n\
                          (Default is '%c').\n", DEFAULT_QUALITY_INDICATOR);
354
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
355 356
  -x, --encoding=ENC      Set the mini-SEED encoding. Either 'steim1' or 'steim2'.\n\
                          (Default is 'steim1').\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
357 358 359 360 361
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
  -r, --reclen            Specify the desired mini-SEED record length in bytes\n\
                          which must be expressible as 2 raised to the power of X\n\
                          where X is between (and including) 8 to 20.\n\
                          (Default is %d).\n", DEFAULT_RECLEN_MINISEED);
362 363 364
#endif


365
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
366 367 368
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
SeedLink arguments:\n");

369
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
370
  -k, --slink=PLUGINID    Send received data to SeedLink as a plug-in.\n\
371
                          Data are sent by send_raw_depoch().\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
372 373
                          This option, inside the file seedlink.ini, must be\n\
                          the last without adding value for PLUGINID!\n\
374 375 376 377 378 379 380
                          PLUGINID is set by SeisComP daemon.\n\
                          Not usable together with -K.\n");

#ifdef HAVE_LIBMSEED
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
  -K, --slinkms=PLUGINID  Send received data to SeedLink as a plug-in.\n\
                          This option is similar to previous -k,\n\
381 382
                          using -K the program converts data into mini-SEED\n\
                          records and sends them by the function send_mseed()\n\
383 384
                          instead of send_raw_depoch().\n\
                          Not usable together with -k.\n");
385
#endif
386

387 388 389 390 391 392
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
  -Q, --timing_quality=TQ This value is used for the functions send_raw*().\n\
                          TQ is %d or in [%d..%d] (default %d).\n",
			  DEFAULT_TIMING_QUALITY, DEFAULT_TIMING_QUALITY_MINIMUM, DEFAULT_TIMING_QUALITY_MAXIMUM,
			  DEFAULT_TIMING_QUALITY);

393 394 395 396 397
#endif

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Other arguments:\n\
  -N, --network=NET       Default output Network code. (default '%s').\n\
398 399
  -n, --location=LOC      Default output Location code. (default is NULL).\n\
                          Location NULL is printed out as '%s'.\n\
400 401 402 403 404 405 406 407 408
  -v, --verbose=LEVEL     Be verbose. LEVEL is a bitmap:\n\
                          %d Channel State, %d Channel, %d Raw Stream,\n\
                          %d CRC32, %d Connection flow,\n\
                          %d Packet Management, %d Extra, %d Date,\n\
                          %d Gap, %d DOD, %d All messages.\n\
  -g, --logdata           Print info about packet data.\n\
  -G, --logsample         Print sample values of packets. Includes -g.\n\
",
	    NMXP_LOG_STR(DEFAULT_NETWORK),
409
	    NMXP_LOG_STR(DEFAULT_NULL_LOCATION),
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
	    NMXP_LOG_D_CHANSTATE,
	    NMXP_LOG_D_CHANNEL,
	    NMXP_LOG_D_RAWSTREAM,
	    NMXP_LOG_D_CRC,
	    NMXP_LOG_D_CONNFLOW,
	    NMXP_LOG_D_PACKETMAN,
	    NMXP_LOG_D_EXTRA,
	    NMXP_LOG_D_DATE,
	    NMXP_LOG_D_GAP,
	    NMXP_LOG_D_DOD,
	    NMXP_LOG_D_ANY
		);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
  -w, --writefile         Dump received packets to a file.\n");

426
#ifndef HAVE_WINDOWS_H
427
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
428 429
  -E, --testport=PORT     Accept 'telnet' connection on PORT\n\
                          for data testing and diagnostic purposes.\n");
430
#endif
431

432
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
433
  -V, --version           Print tool version.\n\
434
  -h, --help              Print this help.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
435 436
\n");

437 438 439 440 441
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Signal handling:\n\
   INT QUIT TERM          Sending these signals to %s causes it\n\
                          to immediately attempt to gracefully terminate.\n\
                          It may take several seconds to complete exiting.\n\
442
   ALRM                   Print current info about Raw Stream buffer.\n\
443 444 445
   USR1                   Force to close a connection and open again\n\
                          without quitting the program. Only for connection\n\
                          in near real-time to NaqsServer.\n\
446 447 448
   HUP PIPE               Ignored. (SIG_IGN)\n\
\n", NMXP_LOG_STR(PACKAGE_NAME));

449
    nmxptool_author_support();
450 451 452 453 454

    /*
    if(long_options) {
	int i=0;
	while(long_options[i].name) {
455 456 457
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "%s %d %d %d %c\n",
	    NMXP_LOG_STR(long_options[i].name), long_options[i].has_arg,
	    (long_options[i].flag)? *(long_options[i].flag) : 0, long_options[i].val, long_options[i].val);
458 459 460 461 462 463 464
	    i++;
	}
    }
    */
}


465 466 467 468 469 470 471 472
#define MAXSIZE_LINE_CHAN_STATE 2048
#define MAXSIZECHANNELSTRINGARGUMENT 8000
#define MAXSIZE_CHANNEL_STRING 64

char *get_channel_list_argument_from_state_file(const char *filename) {
    char *ret_channel_string = NULL;
    char line[MAXSIZE_LINE_CHAN_STATE];
    char str_chan[MAXSIZE_CHANNEL_STRING];
473
    int k, c;
474
    FILE *fstatefile = NULL;
475 476
    int i;
    int flag_insert = 1;
477 478 479 480 481

    fstatefile = fopen(filename, "r");

    /* Read only channel names from state file */
    if(fstatefile) {
482
	ret_channel_string = (char *) NMXP_MEM_MALLOC(MAXSIZECHANNELSTRINGARGUMENT);
483 484 485
	ret_channel_string[0] = 0;
	while(fgets(line, MAXSIZE_LINE_CHAN_STATE, fstatefile) != NULL) {
	    k = 0;
486 487 488 489 490 491 492 493 494 495
	    c = 0;

	    /* eat any white spaces and tabs at the beginning */
	    while(line[k] != 0
		    &&  (line[k] == ' ' ||  line[k] == '\t')
		    &&  k < MAXSIZE_CHANNEL_STRING) {
		k++;
	    }

	    /* copy any character up to the end of the line or # character */
496
	    while(line[k] != 0
497
		    &&  line[k] != '#'
498 499 500
		    &&  line[k] != 10
		    &&  line[k] != 13
		    &&  k < MAXSIZE_CHANNEL_STRING) {
501
		str_chan[c] = line[k];
502
		k++;
503 504 505 506 507 508 509 510 511 512 513
		c++;
	    }
	    str_chan[c] = 0;

	    /* remove possible white spaces and tabs from the end of the str_chan */
	    i = strlen(str_chan);
	    while(i > 0) {
		    if(str_chan[i] == ' ' || str_chan[i] == '\t') {
			str_chan[i] = 0;
		    }
		    i--;
514
	    }
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532

	    /* check if str_chan is blank, before insert into the channel list */
	    flag_insert = 0;
	    i = 0;
	    while(i < strlen(str_chan)  &&  !flag_insert) {
		if(str_chan[i] != ' ') {
		    flag_insert = 1;
		}
		i++;
	    }

	    if(flag_insert) {
		if(ret_channel_string[0] == 0) {
		    strncpy(ret_channel_string, str_chan, MAXSIZECHANNELSTRINGARGUMENT);
		} else {
		    strncat(ret_channel_string, ",", MAXSIZECHANNELSTRINGARGUMENT - strlen(ret_channel_string));
		    strncat(ret_channel_string, str_chan, MAXSIZECHANNELSTRINGARGUMENT - strlen(ret_channel_string));
		}
533
	    } else {
534 535
		nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANSTATE, "Discarded '%s' from station file %s:\n%s",
			NMXP_LOG_STR(str_chan), NMXP_LOG_STR(filename), NMXP_LOG_STR(line));
536 537 538 539
	    }
	}
	fclose(fstatefile);
    }
540 541
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_CHANSTATE, "Channel list: %s\n",
	    NMXP_LOG_STR(ret_channel_string));
542 543 544
    return ret_channel_string;
}

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
int nmxptool_read_time(char *str_input, int32_t *pvalue) {
    char str_value[100];
    int len_int;
    int32_t value;
    int j;
    char unit = 'X';
    int ret_errors = 0;

    value = 0;
    strncpy(str_value, str_input, 100);
    len_int = strlen(str_value);
    if(len_int <= 0) {
	/* ERROR */
	ret_errors++;
    } else {
	j=0;
	while(j < len_int  && str_value[j] >= '0' && str_value[j] <= '9') {
	    j++;
	}
	if(j < len_int) {
	    if(j == len_int-1) {
		unit = str_value[j];
		str_value[j] = 0;
		if(unit == 'm' || unit == 'h' || unit == 'd') {
		    value = atoi(str_value);
		    switch(unit) {
			case 'm' :
			    value *= 60;
			    break;
			case 'h' :
			    value *= ( 60 * 60 );
			    break;
			case 'd' :
			    value *= ( 60 * 60 * 24 );
			    break;
		    }
		} else {
		    ret_errors++;
		    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
			    "Syntax of time '%s' is not correct!\n", NMXP_LOG_STR(str_value));
		}
	    } else {
		ret_errors++;
		nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
			"Syntax of time '%s' is not correct!\n", NMXP_LOG_STR(str_value));
	    }
	} else {
	    /* All numbers, then seconds */
	    value = atoi(str_value);
	}

    }

    *pvalue = value;
    return ret_errors;
}

602
int nmxptool_getopt_long(int argc, char **argv, NMXPTOOL_PARAMS *params)
603
{
604 605
    int ret_errors = 0;

606
    NMXP_TM_T tmp_tmt;
607 608 609 610
    int i;
    char one_time_option[255];
    int c;

611
#ifdef HAVE_LIBMSEED
Matteo Quintiliani's avatar
Matteo Quintiliani committed
612 613
    int flag_reclen_pow = 0;
    int reclen_pow = DEFAULT_RECLEN_MINIMUM;
614
#endif
Matteo Quintiliani's avatar
Matteo Quintiliani committed
615

616
    /*
617 618 619
    int len_int, j;
    char unit = 'X';
    char str_interval[100];
620
    */
621

622 623
    char *sep = NULL;

624 625 626 627 628 629 630 631
    struct option long_options[] =
    {
	/* These options set a flag. */
	/* It is not safe use reference to params in this way */
	/* {"verbose",        no_argument,       &(params->flag_verbose), 1}, */
	/* {"quiet",          no_argument,       &(params->flag_verbose), 0}, */
	/* These options don't set a flag.
	 *                   We distinguish them by their indices. */
632 633 634 635 636 637 638 639 640 641 642 643
	{"hostname",     required_argument, NULL, 'H'},
	{"portpds",      required_argument, NULL, 'P'},
	{"portdap",      required_argument, NULL, 'D'},
	{"channels",     required_argument, NULL, 'C'},
	{"network",      required_argument, NULL, 'N'},
	{"location",     required_argument, NULL, 'n'},
	{"stc",          required_argument, NULL, 'S'},
	{"rate",         required_argument, NULL, 'R'},
	{"start_time",   required_argument, NULL, 's'},
	{"end_time",     required_argument, NULL, 'e'},
	{"interval",     required_argument, NULL, 't'},
	{"delay",        required_argument, NULL, 'd'},
644
	{"span_data",    required_argument, NULL, 'a'},
645 646 647 648 649 650
	{"username",     required_argument, NULL, 'u'},
	{"password",     required_argument, NULL, 'p'},
	{"maxlatency",   required_argument, NULL, 'M'},
	{"timeoutrecv",  required_argument, NULL, 'T'},
	{"verbose",      required_argument, NULL, 'v'},
	{"bufferedt",    required_argument, NULL, 'B'},
651
	{"maxdataretr",  required_argument, NULL, 'A'},
652
	/* Following are flags */
653
	{"logdata",      no_argument,       NULL, 'g'},
Matteo Quintiliani's avatar
Matteo Quintiliani committed
654
	{"logsample",    no_argument,       NULL, 'G'},
655 656 657 658
	{"buffered",     no_argument,       NULL, 'b'},
	{"listchannels", no_argument,       NULL, 'l'},
	{"listchannelsnaqs", no_argument,   NULL, 'L'},
	{"channelinfo",  no_argument,       NULL, 'i'},
659
#ifdef HAVE_LIBMSEED
660
	{"writeseed",    required_argument, NULL, 'm'},
661
	{"outdirseed",   required_argument, NULL, 'o'},
662
	{"quality_indicator", required_argument, NULL, 'q'},
Matteo Quintiliani's avatar
Matteo Quintiliani committed
663 664
	{"encoding",     required_argument, NULL, 'x'},
	{"reclen",       required_argument, NULL, 'r'},
665
#endif
666
	{"writefile",    no_argument,       NULL, 'w'},
667
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
668
	{"slink",        required_argument, NULL, 'k'},
669
#endif
670 671 672 673 674
#ifdef HAVE_LIBMSEED
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
	{"slinkms",      required_argument, NULL, 'K'},
#endif
#endif
675
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
676
	{"timing_quality", required_argument, NULL, 'Q'},
677
#endif
678
#ifndef HAVE_WINDOWS_H
679
	{"socketport",   required_argument, NULL, 'E'},
680
#endif
681
	{"statefile",    required_argument, NULL, 'F'},
682
	{"mschan",       required_argument, NULL, 'f'},
683 684
	{"help",         no_argument,       NULL, 'h'},
	{"version",      no_argument,       NULL, 'V'},
685 686 687
	{0, 0, 0, 0}
    };

688
    char optstr[300] = "H:P:D:C:N:n:S:R:s:e:t:d:a:u:p:M:T:v:B:A:F:f:gGblLiwhV";
689

Matteo Quintiliani's avatar
Matteo Quintiliani committed
690 691 692
    int option_index = 0;


693
#ifdef HAVE_LIBMSEED
694
    strcat(optstr, "m:");
695
    strcat(optstr, "o:");
696 697
    strcat(optstr, "q:");
    strcat(optstr, "x:");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
698
    strcat(optstr, "r:");
699
#endif
700

701

702
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
703
    strcat(optstr, "Q:");
704 705
    strcat(optstr, "k:");
#endif
706

707 708 709 710 711 712
#ifdef HAVE_LIBMSEED
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
    strcat(optstr, "K:");
#endif
#endif

713 714 715
#ifndef HAVE_WINDOWS_H
    strcat(optstr, "E:");
#endif
716 717 718 719 720 721 722 723 724

    /* getopt_long stores the option index here. */
    /* init array for checking one time option */
    for(i=0; i<255; i++) {
	one_time_option[i] = 0;
    }


    /* init params */
725
    memcpy(params, &NMXPTOOL_PARAMS_DEFAULT, sizeof(NMXPTOOL_PARAMS_DEFAULT));
726

727 728 729 730 731 732 733 734 735 736 737 738 739 740
    /* Check number of command line arguments for earthworm */
    if (argc == 2)
    {
	int l = strlen(argv[1]);
	if(l >= 3) {
	    if(argv[1][0] != '-') {
		if(argv[1][l-2] == '.'  &&  argv[1][l-1] == 'd') {
		    params->ew_configuration_file = argv[1];
		    return 0;
		}
	    }
	}
    }

741 742 743 744 745 746 747
    while ( (c = getopt_long (argc, argv, optstr, long_options, &option_index)) != -1) {

	/* BE CAREFUL if use synonym options !!! */
	one_time_option[c]++;

	if(one_time_option[c] > 1) {
	    ret_errors++;
748
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "Replicated option -%c (value %s)\n", c, NMXP_LOG_STR(optarg));
749 750 751 752 753 754 755
	} else {
	    switch (c)
	    {
		case 0:
		    /* If this option set a flag, do nothing else now. */
		    if (long_options[option_index].flag != 0)
			break;
756 757 758 759 760
		    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "option %s",
			    NMXP_LOG_STR(long_options[option_index].name));
		    if (optarg) {
			nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, " with arg %s", NMXP_LOG_STR(optarg));
		    }
761
		    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\n");
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
		    break;

		case 'H':
		    params->hostname = optarg;
		    break;

		case 'P':
		    params->portnumberpds = atoi(optarg);
		    break;

		case 'D':
		    params->portnumberdap = atoi(optarg);
		    break;

		case 'C':
777
		    if(params->channels) {
778 779
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Channels have been already defined by State File (option -F)!\n");
780 781
			ret_errors++;
		    } else {
782
			params->channels = NMXP_MEM_STRDUP(optarg);
783
		    }
784 785 786 787 788 789
		    break;

		case 'N':
		    params->network = optarg;
		    break;

790
		case 'n':
791
		    params->location = optarg;
792 793
		    break;

794 795
		case 'S':
		    params->stc = atoi(optarg);
796
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Short-Term-Completion %d.\n", params->stc);
797 798 799
		    if(params->stc >= 0) {
			params->rate = 0; // original sample rate
		    }
800 801 802 803 804 805
		    break;

		case 'R':
		    params->rate = atoi(optarg);
		    break;

806
		case 's':
807
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
808
			/* MESSAGE ERROR */
Matteo Quintiliani's avatar
Matteo Quintiliani committed
809
			ret_errors++;
810
		    } else {
811
			params->start_time = nmxp_data_tm_to_time(&tmp_tmt);
812 813 814 815
		    }
		    break;

		case 'e':
816
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
817
			/* MESSAGE ERROR */
Matteo Quintiliani's avatar
Matteo Quintiliani committed
818
			ret_errors++;
819
		    } else {
820
			params->end_time = nmxp_data_tm_to_time(&tmp_tmt);
821 822 823
		    }
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
824
		case 't':
825
		    ret_errors += nmxptool_read_time(optarg, &(params->interval) );
Matteo Quintiliani's avatar
Matteo Quintiliani committed
826 827
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
828
		case 'd':
829
		    ret_errors += nmxptool_read_time(optarg, &(params->delay) );
Matteo Quintiliani's avatar
Matteo Quintiliani committed
830 831
		    break;

832 833 834 835
		case 'a':
		    ret_errors += nmxptool_read_time(optarg, &(params->span_data) );
		    break;

836 837 838 839 840 841 842 843
		case 'u':
		    params->datas_username = optarg;
		    break;

		case 'p':
		    params->datas_password = optarg;
		    break;

844
		case 'M':
Matteo Quintiliani's avatar
Matteo Quintiliani committed
845
		    params->max_tolerable_latency = atoi(optarg);
846 847
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Max_tolerable_latency %d\n",
			    params->max_tolerable_latency);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
848 849
		    break;

850
		case 'T':
851
		    params->timeoutrecv = atoi(optarg);
852 853
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Time-out receiving %d\n",
			    params->timeoutrecv);
854 855
		    break;

856 857 858 859
		case 'v':
		    params->verbose_level = atoi(optarg);
		    break;

860 861 862
		case 'B':
		    params->flag_buffered = 1;
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
863
			/* MESSAGE ERROR */
864 865 866 867 868 869
			ret_errors++;
		    } else {
			params->buffered_time = nmxp_data_tm_to_time(&tmp_tmt);
		    }
		    break;

870 871
		case 'A':
		    if(optarg) {
872
			params->max_data_to_retrieve = atoi(optarg);
873
		    }
874
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Max_time_to_retrieve %d\n", params->max_data_to_retrieve);
875
		    break;
876

877 878 879
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
		case 'k':
		    params->flag_slink = 1;
880 881 882 883 884 885 886 887 888
		    if(params->flag_slinkms) {
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Options -k and -K are declared in the same command line!\n");
			ret_errors++;
		    } else {
			params->plugin_slink = optarg;
			if(params->plugin_slink) {
			    nmxp_log_set_prefix(params->plugin_slink);
			}
889
		    }
890 891 892
		    break;
#endif

893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
#ifdef HAVE_LIBMSEED
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
		case 'K':
		    params->flag_slinkms = 1;
		    if(params->flag_slink) {
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Options -k and -K are declared in the same command line!\n");
			ret_errors++;
		    } else {
			params->plugin_slink = optarg;
			if(params->plugin_slink) {
			    nmxp_log_set_prefix(params->plugin_slink);
			}
		    }
		    break;
#endif
#endif
910 911

#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
912 913 914
		case 'Q':
		    params->timing_quality = atoi(optarg);
		    break;
915
#endif
916

917
#ifndef HAVE_WINDOWS_H
918 919
		case 'E':
		    params->listen_port = atoi(optarg);
920
		    break;
921
#endif
922

923 924
		case 'F':
		    params->statefile = optarg;
925 926 927 928 929 930
		    if(params->channels == NULL) {
			params->channels = get_channel_list_argument_from_state_file(params->statefile);
			if(params->channels) {
			    /* Do nothing */
			} else {
			    ret_errors++;
931 932
			    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY,
				    "State file %s not found or unable to read!\n", NMXP_LOG_STR(params->statefile));
933
			}
934 935
		    } else {
			ret_errors++;
936 937
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Channels have been already defined by option -C!\n");
938 939 940
		    }
		    break;

941 942 943 944 945
		case 'f':
		    sep = strstr(optarg, "/");
		    if(sep) {
			sep[0] = 0;
			sep++;
946
			params->usec = atoi(optarg) * 1000;
947
			params->n_channel = atoi(sep);
948 949
			nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY,
				"Channels %d usec %d!\n", params->n_channel, params->usec);
950 951
		    } else {
			ret_errors++;
952 953
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Syntax error in option -%c %s!\n", c, NMXP_LOG_STR(optarg));
954 955 956
		    }
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
957
		case 'g':
958 959 960
		    params->flag_logdata = 1;
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
961
		case 'G':
Matteo Quintiliani's avatar
Matteo Quintiliani committed
962
		    params->flag_logdata = 1;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
963 964 965
		    params->flag_logsample = 1;
		    break;

966
		case 'b':
967
		    params->flag_buffered = 1;
968 969
		    break;

970 971 972 973
		case 'l':
		    params->flag_listchannels = 1;
		    break;

974 975 976 977
		case 'L':
		    params->flag_listchannelsnaqs = 1;
		    break;

978 979 980 981
		case 'i':
		    params->flag_request_channelinfo = 1;
		    break;

982 983
#ifdef HAVE_LIBMSEED
		case 'm':
984 985 986 987 988 989 990 991 992 993 994 995 996
		    if(optarg && strlen(optarg) == 1) {
			params->type_writeseed = optarg[0];
			if(params->type_writeseed != TYPE_WRITESEED_SDS
				&& params->type_writeseed != TYPE_WRITESEED_BUD) {
			    ret_errors++;
			    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				    "Syntax error in option -%c %s!\n", c, NMXP_LOG_STR(optarg));
			}
		    } else {
			ret_errors++;
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Syntax error in option -%c %s!\n", c, NMXP_LOG_STR(optarg));
		    }
997
		    break;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
998

999 1000 1001
		case 'o':
		    params->outdirseed = optarg;
		    if(params->outdirseed) {
1002 1003 1004 1005 1006
			if(nmxp_data_dir_exists(params->outdirseed)) {
			    params->outdirseed =  nmxp_data_dir_abspath(params->outdirseed);
			} else {
			    ret_errors++;
			    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY,
1007
				    "Mini-SEED output directory %s does not exist!\n", NMXP_LOG_STR(params->outdirseed));
1008 1009 1010
			}
		    }
		    break;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
1011

1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
                case 'q':
                    switch(optarg[0]) {
                      case 'D':
                      case 'R':
                      case 'Q':
                      case 'M':
                        params->quality_indicator = optarg[0];
                        break;
                      default:
                        ret_errors++;
                        nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY,
                               "Quality indicator %s is invalid! Must be D, R, Q or M!\n", NMXP_LOG_STR(optarg));
                        break;
                    }
Matteo Quintiliani's avatar
Matteo Quintiliani committed
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
		    break;

		case 'x':
		    if (strcmp(optarg,"steim1") == 0) {
			params->encoding = DE_STEIM1;
		    } else if (strcmp(optarg,"steim2") == 0) {
			params->encoding = DE_STEIM2;
		    } else {
			ret_errors++;
			nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY,
				"Encoding %s is invalid! Must either be steim1 or steim2!\n",NMXP_LOG_STR(optarg));
		    }
		    break;

		case 'r':
		    params->reclen = atoi(optarg);
		    if(params->reclen >= DEFAULT_RECLEN_MINIMUM  &&  params->reclen <= DEFAULT_RECLEN_MAXIMUM) {
			flag_reclen_pow = 0;
			while(!flag_reclen_pow  &&  reclen_pow <= DEFAULT_RECLEN_MAXIMUM) {
			    if(params->reclen == reclen_pow) {
				flag_reclen_pow = 1;
			    }
			    reclen_pow *= 2;
			}
			if(!flag_reclen_pow) {
			    ret_errors++;
			    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY,
				    "reclen must expressible as 2 raised to the power of X where X is between (and including) 8 to 20.\n");
			}
		    } else {
			ret_errors++;
			nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY,
				"reclen must expressible as 2 raised to the power of X where X is between (and including) 8 to 20.\n");
		    }
		    break;
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
#endif

		case 'w':
		    params->flag_writefile = 1;
		    break;

		case 'h':
		    nmxptool_usage(long_options);
		    exit (1);
		    break;

1072 1073
		case 'V':
		    nmxptool_version();
Matteo Quintiliani's avatar
Matteo Quintiliani committed
1074
		    nmxptool_author_support();
1075 1076 1077
		    exit (1);
		    break;

1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
		case '?':
		    /* getopt_long already printed an error message. */
		    ret_errors++;
		    break;

		default:
		    nmxptool_usage(long_options);
		    exit (1);
	    }
	}
    }

    /* Print any remaining command line arguments (not options). */
    if (optind < argc)
    {
	ret_errors += optind;

1095
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "non-option ARGV-elements: ");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
1096 1097
	while (optind < argc) {
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%s ",
1098 1099
		    NMXP_LOG_STR(argv[optind]));
	    optind++;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
1100
	}
1101 1102 1103
	putchar ('\n');
    }

1104 1105 1106 1107 1108 1109
    if(params->statefile) {
	params->flag_buffered = 1;
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY,
		"Enable buffer for requesting also recent packets into the past.\n");
    }

1110 1111 1112 1113
    return ret_errors;
}


1114 1115 1116 1117 1118
void nmxptool_log_params(NMXPTOOL_PARAMS *params) {
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
    char *hostname: %s\n\
    int portnumberdap: %d\n\
    int portnumberpds: %d\n\
Matteo Quintiliani's avatar