nmxptool_getoptlong.c 29 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.76 2008-03-03 07:56:11 mtheo Exp $
Matteo Quintiliani's avatar
Matteo Quintiliani committed
11 12 13
 *
 */

14 15 16 17 18 19 20 21 22 23
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include "config.h"
#include "nmxp.h"

#include "nmxptool_getoptlong.h"


24
const NMXPTOOL_PARAMS NMXPTOOL_PARAMS_DEFAULT =
25 26
{
    NULL,
27 28
    DEFAULT_PORT_DAP,
    DEFAULT_PORT_PDS,
29 30 31
    NULL,
    NULL,
    NULL,
32 33
    0.0,
    0.0,
34
    DEFAULT_INTERVAL_NO_VALUE,
35 36
    NULL,
    NULL,
37 38
    DEFAULT_STC,
    DEFAULT_RATE,
39
    NULL,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
40
    DEFAULT_DELAY,
41 42
    DEFAULT_MAX_TOLERABLE_LATENCY,
    DEFAULT_TIMEOUTRECV,
43
    DEFAULT_VERBOSE_LEVEL,
44
    NULL,
45
    NULL,
46
    DEFAULT_BUFFERED_TIME,
47
    DEFAULT_MAX_TIME_TO_RETRIEVE,
48
    0,
49 50 51 52
    0,
    0,
    0,
    0,
53
    0,
54
    0,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
55
    0,
56 57 58
    0
};

59 60

void nmxptool_author_support() {
61
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
62 63
Matteo Quintiliani - Istituto Nazionale di Geofisica e Vulcanologia - Italy\n\
Mail bug reports and suggestions to <%s>.\n",
64
	    NMXP_LOG_STR(PACKAGE_BUGREPORT)
65 66 67 68 69
	    );
}


void nmxptool_version() {
70
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
71
%s %s%s, Nanometrics tool based on %s\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
72
        (Private Data Stream 1.4, Data Access Protocol 1.0)\n",
73
	NMXP_LOG_STR(PACKAGE_NAME), NMXP_LOG_STR(PACKAGE_VERSION), NMXP_LOG_STR(PACKAGE_BUILD),
74
	nmxp_log_version()	
75
	);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
76 77

    nmxptool_supports();
78 79
}

Matteo Quintiliani's avatar
Matteo Quintiliani committed
80
void nmxptool_supports() {
81
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
82 83
         Support for: libmseed ");
#ifdef HAVE_LIBMSEED
84
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "YES");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
85
#else
86
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "NO");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
87 88
#endif

89
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ", SeedLink ");
90
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
91
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "YES");
92
#else
93
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "NO");
94 95
#endif

96
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ", Earthworm ");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
97
#ifdef HAVE_EARTHWORMOBJS
98
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "YES");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
99
#else
100
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "NO");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
101
#endif
102
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, ".\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
103 104
}

105

106 107
void nmxptool_usage(struct option long_options[])
{
108
    nmxptool_version();
Matteo Quintiliani's avatar
Matteo Quintiliani committed
109

110
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
111
\n\
112
Usage: %s -H hostname   -l | -L\n\
113 114
             Print list of available Time Series channels\n\
             on DataServer and NaqsServer respectively.\n\
115 116
\n\
       %s -H hostname -C channellist [...]\n\
117
             Receive data in near real-time from NaqsServer by PDS.\n\
118
\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
119
       %s -H hostname -F statefile [-A SECs] [...]\n\
120
             Receive data from NaqsServer, and from DataServer if is necessary.\n\
121 122
\n\
       %s -H hostname -C channellist -s DATE -e DATE [...]\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
123
       %s -H hostname -C channellist -s DATE -t SECs [...]\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
124
             Receive data from DataServer by DAP.\n\
125 126 127 128 129 130
\n",
NMXP_LOG_STR(PACKAGE_NAME),
NMXP_LOG_STR(PACKAGE_NAME),
NMXP_LOG_STR(PACKAGE_NAME),
NMXP_LOG_STR(PACKAGE_NAME),
NMXP_LOG_STR(PACKAGE_NAME));
Matteo Quintiliani's avatar
Matteo Quintiliani committed
131 132

#ifdef HAVE_EARTHWORMOBJS
133
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
134
       %s nmxptool.d\n\
135
             Launched as Earthworm module to redirect data into the EW-Rings.\n\
136
\n", NMXP_LOG_STR(PACKAGE_NAME));
137 138 139 140 141 142
#endif

#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
       %s <option ... option> -k\n\
             Launched as SeedLink plug-in to feed the SL-Server.\n\
143
\n", NMXP_LOG_STR(PACKAGE_NAME));
Matteo Quintiliani's avatar
Matteo Quintiliani committed
144 145
#endif

146
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
147 148
       %s --help\n\
             Print this help.\n\
149
\n", NMXP_LOG_STR(PACKAGE_NAME));
150 151

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
152
Main arguments:\n\
153 154
  -H, --hostname=HOST     NaqsServer or DataServer hostname.\n\
  -C, --channels=LIST     List of NET.STA.CHAN separated by comma.\n\
155
                          NET  is optional and used only for output.\n\
156 157
                          STA  can be '*', it stands for all stations.\n\
                          CHAN can contain '?', it stands for any character.\n\
158 159
			  Network code will be assigned from the first\n\
                          pattern that includes station and channel.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
160
                          DO NOT USE with -F.\n\
161 162 163 164 165
                                Example: N1.AAA.HH?,N2.*.HH?,MMM.BH?\n\
                          Second pattern includes the first. Unless AAA, all\n\
                          stations with HH channels will have network to N2.\n\
                          Station MMM will have default network defined by -N.\n\
  -F, --statefile=FILE    List of pattern channels like -C. One for each line.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
166 167 168
                          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\
169 170
                          Allow data continuity between program restarts.\n\
                          Related to -A and it enables -b.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
171 172 173
                          DO NOT USE with -C.\n",
			  NMXP_STR_STATE_EXT
);
174 175

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
176
  -A, --maxdataretr=SECs  Max amount of data of the past to retrieve from the\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
177
                          DataServer when program restarts (default %d) [%d..%d].\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
178 179 180 181
                          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\
                          Related to -F.\n\
182 183 184 185 186 187 188
\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
189 190
PDS arguments for NaqsServer:\n\
  -P, --portpds=PORT      NaqsServer port number (default %d).\n\
191 192
  -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
193
                             Packets contain compressed data. Related to -M, -T.\n\
194 195
                             It enables --rate=-1.\n\
                           0 decompressed packets are received in chronological\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
196
                             order without waiting for missing packets.\n\
197
                          [1..300] decompressed packets are received in\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
198
                             chronological order but waiting for missing packets\n\
199
                             at most SECs seconds.\n\
200 201 202 203 204 205 206
  -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\
  -B, --buff_date=DATE    Request also recent packets into the past\n\
                          but consider only samples after DATE.\n\
207
  -L, --listchannelsnaqs  List of available Time Series channels on NaqsServer.\n\
208 209
  -M, --maxlatency=SECs   Max tolerable latency (default %d) [%d..%d].\n\
  -T, --timeoutrecv=SECs  Time-out for flushing buffered packets.\n\
210
                          (default %d, no time-out) [%d..%d].\n\
211
                          -T is useful for retrieving Data On Demand.\n\
212
                          -M, -T are usable only with Raw Stream, -S=-1.\n\
213 214 215
                          In general, -M and -T are not used together.\n\
\n\
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
216
	    DEFAULT_PORT_PDS,
217 218 219 220 221 222 223 224 225 226 227
	    DEFAULT_STC,
	    DEFAULT_RATE,
	    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
228
DAP arguments for DataServer:\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
229
  -D, --portdap=PORT      DataServer port number (default %d).\n\
230 231 232 233 234 235 236
  -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\
237 238 239
  -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
240
                          DO NOT USE with -e.\n\
241 242 243
  -d, --delay=SECs        Receive continuosly data with delay [%d..%d].\n\
  -u, --username=USER     DataServer username.\n\
  -p, --password=PASS     DataServer password.\n\
244
  -l, --listchannels      List of available Time Series channels on DataServer.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
245
  -i, --channelinfo       Print channelinfo (network name) when using -l.\n\
246 247
\n\
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
248
DEFAULT_PORT_DAP,
249
(DEFAULT_INTERVAL_MAXIMUM / 86400),
250 251
DEFAULT_DELAY_MINIMUM,
DEFAULT_DELAY_MAXIMUM);
252

253
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
254
Other arguments:\n\
255
  -N, --network=NET       Default output Network code. (default '%s').\n\
256
  -n, --location=LOC      Default output Location code. DISABLED!\n\
257
  -v, --verbose=level     Be verbose. level is a bitmap:\n\
258
                          %d Channel State, %d Channel, %d Raw Stream,\n\
259 260 261
                          %d CRC32, %d Connection flow,\n\
                          %d Packet Management, %d Extra, %d Date,\n\
                          %d Gap, %d DOD, %d All messages.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
262
  -g, --logdata           Print info about packet data.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
263
  -G, --logsample         Print sample values of packets. Includes -g.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
264
",
265
	    NMXP_LOG_STR(DEFAULT_NETWORK),
266
	    NMXP_LOG_D_CHANSTATE,
267 268 269 270 271 272 273 274 275 276
	    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
277 278 279
		);

#ifdef HAVE_LIBMSEED
280
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
281 282
  -m, --writeseed         Pack received data in Mini-SEED records\n\
                          and write to a file.\n");
283 284
#endif

285
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
286
  -w, --writefile         Dump received packets to a file.\n");
287

288
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
289
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
290
  -k, --slink=pluginid    Send received data to SeedLink as a plug-in.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
291
                          THIS OPTION, INSIDE THE FILE seedlink.ini, MUST BE\n\
292 293
                          THE LAST WITHOUT ADDING VALUE FOR pluginid!\n\
                          pluginid is set by SeisComP daemon.\n");
294
#endif
295

296
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
297
  -V, --version           Print tool version.\n\
298
  -h, --help              Print this help.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
299 300
\n");

301
    nmxptool_author_support();
302 303 304 305 306

    /*
    if(long_options) {
	int i=0;
	while(long_options[i].name) {
307 308 309
	    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);
310 311 312 313 314 315 316
	    i++;
	}
    }
    */
}


317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
#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];
    int k;
    FILE *fstatefile = NULL;

    fstatefile = fopen(filename, "r");

    /* Read only channel names from state file */
    if(fstatefile) {
	ret_channel_string = (char *) malloc (MAXSIZECHANNELSTRINGARGUMENT);
	ret_channel_string[0] = 0;
	while(fgets(line, MAXSIZE_LINE_CHAN_STATE, fstatefile) != NULL) {
	    k = 0;
	    while(line[k] != 0
		    &&  line[k] != ' '
		    &&  line[k] != 10
		    &&  line[k] != 13
		    &&  k < MAXSIZE_CHANNEL_STRING) {
		str_chan[k] = line[k];
		k++;
	    }
	    str_chan[k] = 0;
	    if(ret_channel_string[0] == 0) {
		strncpy(ret_channel_string, str_chan, MAXSIZECHANNELSTRINGARGUMENT);
	    } else {
		strncat(ret_channel_string, ",", MAXSIZECHANNELSTRINGARGUMENT);
		strncat(ret_channel_string, str_chan, MAXSIZECHANNELSTRINGARGUMENT);
	    }
	}
	fclose(fstatefile);
    }
    return ret_channel_string;
}

357
int nmxptool_getopt_long(int argc, char **argv, NMXPTOOL_PARAMS *params)
358
{
359 360
    int ret_errors = 0;

361
    NMXP_TM_T tmp_tmt;
362 363 364 365
    int i;
    char one_time_option[255];
    int c;

366 367 368 369
    int len_int, j;
    char unit = 'X';
    char str_interval[100];

370 371 372 373 374 375 376 377
    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. */
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
	{"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'},
	{"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'},
396
	{"maxdataretr",  required_argument, NULL, 'A'},
397
	/* Following are flags */
398
	{"logdata",      no_argument,       NULL, 'g'},
Matteo Quintiliani's avatar
Matteo Quintiliani committed
399
	{"logsample",    no_argument,       NULL, 'G'},
400 401 402 403
	{"buffered",     no_argument,       NULL, 'b'},
	{"listchannels", no_argument,       NULL, 'l'},
	{"listchannelsnaqs", no_argument,   NULL, 'L'},
	{"channelinfo",  no_argument,       NULL, 'i'},
404
#ifdef HAVE_LIBMSEED
405
	{"writeseed",    no_argument,       NULL, 'm'},
406
#endif
407
	{"writefile",    no_argument,       NULL, 'w'},
408
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
409
	{"slink",        required_argument, NULL, 'k'},
410
#endif
411 412 413
	{"statefile",    required_argument, NULL, 'F'},
	{"help",         no_argument,       NULL, 'h'},
	{"version",      no_argument,       NULL, 'V'},
414 415 416
	{0, 0, 0, 0}
    };

Matteo Quintiliani's avatar
Matteo Quintiliani committed
417
    char optstr[300] = "H:P:D:C:N:n:S:R:s:e:t:d:u:p:M:T:v:B:A:F:gGblLiwhV";
418

Matteo Quintiliani's avatar
Matteo Quintiliani committed
419 420 421
    int option_index = 0;


422 423 424
#ifdef HAVE_LIBMSEED
    strcat(optstr, "m");
#endif
425

426 427 428
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
    strcat(optstr, "k:");
#endif
429 430 431 432 433 434 435 436 437 438


    /* 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 */
439
    memcpy(params, &NMXPTOOL_PARAMS_DEFAULT, sizeof(NMXPTOOL_PARAMS_DEFAULT));
440

441 442 443 444 445 446 447 448 449 450 451 452 453 454
    /* 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;
		}
	    }
	}
    }

455 456 457 458 459 460 461
    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++;
462
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "Replicated option -%c (value %s)\n", c, NMXP_LOG_STR(optarg));
463 464 465 466 467 468 469
	} else {
	    switch (c)
	    {
		case 0:
		    /* If this option set a flag, do nothing else now. */
		    if (long_options[option_index].flag != 0)
			break;
470 471 472 473 474
		    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));
		    }
475
		    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\n");
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
		    break;

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

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

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

		case 'C':
491
		    if(params->channels) {
492 493
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Channels have been already defined by State File (option -F)!\n");
494 495 496 497
			ret_errors++;
		    } else {
			params->channels = optarg;
		    }
498 499 500 501 502 503
		    break;

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

504
		case 'n':
505 506 507 508 509
		    if(1) {
			nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY, "Location is currently disabled!\n");
		    } else {
			params->location = optarg;
		    }
510 511
		    break;

512 513
		case 'S':
		    params->stc = atoi(optarg);
514
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Short-Term-Completion %d.\n", params->stc);
515 516 517 518 519 520
		    break;

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

521
		case 's':
522
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
523
			/* MESSAGE ERROR */
Matteo Quintiliani's avatar
Matteo Quintiliani committed
524
			ret_errors++;
525
		    } else {
526
			params->start_time = nmxp_data_tm_to_time(&tmp_tmt);
527 528 529 530
		    }
		    break;

		case 'e':
531
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
532
			/* MESSAGE ERROR */
Matteo Quintiliani's avatar
Matteo Quintiliani committed
533
			ret_errors++;
534
		    } else {
535
			params->end_time = nmxp_data_tm_to_time(&tmp_tmt);
536 537 538
		    }
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
539
		case 't':
540 541 542 543 544 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
		    strncpy(str_interval, optarg, 100);
		    len_int = strlen(str_interval);
		    if(len_int <= 0) {
			/* ERROR */
			ret_errors++;
		    } else {
			j=0;
			while(j < len_int  && str_interval[j] >= '0' && str_interval[j] <= '9') {
			    j++;
			}
			if(j < len_int) {
			    if(j == len_int-1) {
				unit = str_interval[j];
				str_interval[j] = 0;
				if(unit == 'm' || unit == 'h' || unit == 'd') {
				    params->interval = atoi(str_interval);
				    switch(unit) {
					case 'm' :
					    params->interval *= 60;
					    break;
					case 'h' :
					    params->interval *= ( 60 * 60 );
					    break;
					case 'd' :
					    params->interval *= ( 60 * 60 * 24 );
					    break;
				    }
				} else {
				    ret_errors++;
				    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
					    "Syntax of interval is not correct!\n");
				}
			    } else {
				ret_errors++;
				nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
					"Syntax of interval is not correct!\n");
			    }
			} else {
			    /* All numbers, then seconds */
			    params->interval = atoi(str_interval);
			}

		    }

Matteo Quintiliani's avatar
Matteo Quintiliani committed
584 585
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
586 587 588 589
		case 'd':
		    params->delay = atoi(optarg);
		    break;

590 591 592 593 594 595 596 597
		case 'u':
		    params->datas_username = optarg;
		    break;

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

598
		case 'M':
Matteo Quintiliani's avatar
Matteo Quintiliani committed
599
		    params->max_tolerable_latency = atoi(optarg);
600 601
		    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
602 603
		    break;

604
		case 'T':
605
		    params->timeoutrecv = atoi(optarg);
606 607
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Time-out receiving %d\n",
			    params->timeoutrecv);
608 609
		    break;

610 611 612 613
		case 'v':
		    params->verbose_level = atoi(optarg);
		    break;

614 615 616
		case 'B':
		    params->flag_buffered = 1;
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
617
			/* MESSAGE ERROR */
618 619 620 621 622 623
			ret_errors++;
		    } else {
			params->buffered_time = nmxp_data_tm_to_time(&tmp_tmt);
		    }
		    break;

624 625
		case 'A':
		    if(optarg) {
626
			params->max_data_to_retrieve = atoi(optarg);
627
		    }
628
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Max_time_to_retrieve %d\n", params->max_data_to_retrieve);
629
		    break;
630

631 632 633 634 635 636 637
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
		case 'k':
		    params->flag_slink = 1;
		    params->plugin_slink = optarg;
		    break;
#endif

638
		case 'F':
639
		    params->flag_buffered = 1;
640
		    params->statefile = optarg;
641 642 643 644 645 646
		    if(params->channels == NULL) {
			params->channels = get_channel_list_argument_from_state_file(params->statefile);
			if(params->channels) {
			    /* Do nothing */
			} else {
			    ret_errors++;
647 648
			    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));
649
			}
650 651
		    } else {
			ret_errors++;
652 653
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Channels have been already defined by option -C!\n");
654 655 656
		    }
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
657
		case 'g':
658 659 660
		    params->flag_logdata = 1;
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
661
		case 'G':
Matteo Quintiliani's avatar
Matteo Quintiliani committed
662
		    params->flag_logdata = 1;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
663 664 665
		    params->flag_logsample = 1;
		    break;

666
		case 'b':
667
		    params->flag_buffered = 1;
668 669
		    break;

670 671 672 673
		case 'l':
		    params->flag_listchannels = 1;
		    break;

674 675 676 677
		case 'L':
		    params->flag_listchannelsnaqs = 1;
		    break;

678 679 680 681
		case 'i':
		    params->flag_request_channelinfo = 1;
		    break;

682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
#ifdef HAVE_LIBMSEED
		case 'm':
		    params->flag_writeseed = 1;
		    break;
#endif

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

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

697 698
		case 'V':
		    nmxptool_version();
Matteo Quintiliani's avatar
Matteo Quintiliani committed
699
		    nmxptool_author_support();
700 701 702
		    exit (1);
		    break;

703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
		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;

720
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "non-option ARGV-elements: ");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
721 722
	while (optind < argc) {
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%s ",
723 724
		    NMXP_LOG_STR(argv[optind]));
	    optind++;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
725
	}
726 727 728 729 730 731 732
	putchar ('\n');
    }

    return ret_errors;
}


733 734 735 736 737
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\
738
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
739
    NMXP_LOG_STR(params->hostname),
740 741 742 743 744
    params->portnumberdap,
    params->portnumberpds
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
745
    char *channels: %s\n\
746
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
747
    NMXP_LOG_STR(params->channels)
748 749 750
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
751 752 753 754 755
    char *network: %s\n\
    char *location: %s\n\
    double start_time: %f\n\
    double end_time: %f\n\
    int32_t interval: %d\n\
756
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
757 758
    NMXP_LOG_STR(params->network),
    NMXP_LOG_STR(params->location),
759 760 761 762 763 764 765
    params->start_time,
    params->end_time,
    params->interval
);


    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
766 767
    char *datas_username: %s\n\
    char *datas_password: %s\n\
768
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
769 770
    NMXP_LOG_STR(params->datas_username),
    NMXP_LOG_STR(params->datas_password)
771 772 773
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
774 775 776 777 778 779 780
    int32_t stc: %d\n\
    int32_t rate: %d\n\
    char *plugin_slink: %s\n\
    int32_t delay: %d\n\
    int32_t max_tolerable_latency: %d\n\
    int32_t timeoutrecv: %d\n\
    int32_t verbose_level: %d\n\
781 782 783
",
    params->stc,
    params->rate,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
784
    NMXP_LOG_STR(params->plugin_slink),
785 786 787 788 789 790 791
    params->delay,
    params->max_tolerable_latency,
    params->timeoutrecv,
    params->verbose_level
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
792 793
    char *ew_configuration_file: %s\n\
    char *statefile: %s\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
794
    int32_t max_data_to_retrieve: %d\n\
795
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
796 797
    NMXP_LOG_STR(params->ew_configuration_file),
    NMXP_LOG_STR(params->statefile),
Matteo Quintiliani's avatar
Matteo Quintiliani committed
798
    params->max_data_to_retrieve
799 800 801
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
802 803 804 805 806 807 808 809 810
    double buffered_time: %f\n\
    int flag_writeseed: %d\n\
    int flag_listchannels: %d\n\
    int flag_listchannelsnaqs: %d\n\
    int flag_request_channelinfo: %d\n\
    int flag_writefile: %d\n\
    int flag_slink: %d\n\
    int flag_buffered: %d\n\
    int flag_logdata: %d\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
811
    int flag_logsample: %d\n\
812 813 814 815 816 817 818 819 820
",
    params->buffered_time,
    params->flag_writeseed,
    params->flag_listchannels,
    params->flag_listchannelsnaqs,
    params->flag_request_channelinfo,
    params->flag_writefile,
    params->flag_slink,
    params->flag_buffered,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
821 822
    params->flag_logdata,
    params->flag_logsample
823 824 825
    );
}

826 827


828
int nmxptool_check_params(NMXPTOOL_PARAMS *params) {
829 830
    int ret = 0;

831 832 833
    if(params->ew_configuration_file != NULL) {
	/* Do nothing */
    } else if(params->hostname == NULL) {
834
	ret = -1;
835
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<hostname> is required!\n");
836
    } else if(params->flag_listchannels) {
837 838 839 840 841
	if(params->flag_listchannelsnaqs) {
	    ret = -1;
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "-l and -L can not be used together!\n");
	}
    } else if(params->flag_listchannelsnaqs) {
842 843 844
	/* Do nothing */
    } else if(params->hostname == NULL) {
	ret = -1;
845
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<hostname> is required!\n");
846 847
    } else if(params->channels == NULL) {
	ret = -1;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
848
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "Channel list is required!\n");
849
    } else if(params->start_time == 0.0 &&  params->end_time != 0.0) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
850
	ret = -1;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
851
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<end_time> is required when declaring <start_time>!\n");
852
    } else if(params->start_time != 0.0  &&  params->end_time != 0.0  && params->interval != DEFAULT_INTERVAL_NO_VALUE) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
853
	ret = -1;
854
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<start_time> has to be used with either <end_time> or <interval>!\n");
855 856 857
    } else if(params->interval != DEFAULT_INTERVAL_NO_VALUE && params->interval <= 0) {
	ret = -1;
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<interval> has to be greater than zero!\n");
858 859 860
    } else if(params->interval > DEFAULT_INTERVAL_MAXIMUM) {
	ret = -1;
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<interval> has to be less than %d seconds (%d days)!\n", DEFAULT_INTERVAL_MAXIMUM, DEFAULT_INTERVAL_MAXIMUM / 86400);
861
    } else if(params->start_time != 0.0   &&   params->end_time != 0.0
862
	    && params->start_time >= params->end_time) {
863
	ret = -1;
864
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<start_time> is less than <end_time>!\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
865
    } else if(params->stc < DEFAULT_STC_MINIMUM   ||   params->stc > DEFAULT_STC_MAXIMUM) {
866
	ret = -1;
867
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<stc> has to be in the interval [%d..%d] secs.\n",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
868
		DEFAULT_STC_MINIMUM, DEFAULT_STC_MAXIMUM);
869 870
    } else if(params->stc == -1   &&   params->rate != DEFAULT_RATE) {
	ret = -1;
871
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<rate> has to be equal to -1 when <stc> is equal to -1 (Raw Stream).\n");
872
    } else if(params->delay > 0 && params->start_time != 0.0   &&   params->end_time != 0.0) {
873
	ret = -1;
874
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<delay> can not be used with options <start_time> and <end_time>.\n");
875 876 877
    } else if( params->delay != DEFAULT_DELAY &&
	    (params->delay < DEFAULT_DELAY_MINIMUM  || params->delay > DEFAULT_DELAY_MAXIMUM) ) {
	ret = -1;
878
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<delay> has to be in the interval [%d..%d] secs.\n",
879
		DEFAULT_DELAY_MINIMUM, DEFAULT_DELAY_MAXIMUM);
880 881 882 883
    } else if(params->verbose_level < DEFAULT_VERBOSE_LEVEL_MINIMUM  ||  params->verbose_level > DEFAULT_VERBOSE_LEVEL_MAXIMUM) {
	ret = -1;
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<verbose_level> has to be in the interval [%d..%d].\n",
		DEFAULT_VERBOSE_LEVEL_MINIMUM, DEFAULT_VERBOSE_LEVEL_MAXIMUM);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
884 885
    } else if(params->rate < DEFAULT_RATE_MINIMUM  ||  params->rate > DEFAULT_RATE_MAXIMUM) {
	ret = -1;
886
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<rate> has to be in the interval [%d..%d].\n",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
887
		DEFAULT_RATE_MINIMUM, DEFAULT_RATE_MAXIMUM);
888
    } else if(params->rate != -1 && params->start_time != 0.0   &&   params->end_time != 0.0) {
889
	ret = -1;
890
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<rate> can not be used with options <start_time> and <end_time>.\n");
891
    } else if(params->flag_buffered != 0 && params->start_time != 0.0   &&   params->end_time != 0.0) {
892
	ret = -1;
893
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY, "<buffered> can not be used with options <start_time> and <end_time>.\n");
894 895
    } else if( (params->max_data_to_retrieve < DEFAULT_MAX_TIME_TO_RETRIEVE_MINIMUM  ||
		params->max_data_to_retrieve > DEFAULT_MAX_TIME_TO_RETRIEVE_MAXIMUM)) {
896
	ret = -1;
897
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<maxdataretr> has to be within [%d..%d].\n",
898 899
		DEFAULT_MAX_TIME_TO_RETRIEVE_MINIMUM,
		DEFAULT_MAX_TIME_TO_RETRIEVE_MAXIMUM);
900
    } else if( params->stc == -1
901 902
	    && (params->max_tolerable_latency < DEFAULT_MAX_TOLERABLE_LATENCY_MINIMUM  ||
		params->max_tolerable_latency > DEFAULT_MAX_TOLERABLE_LATENCY_MAXIMUM)) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
903
	ret = -1;
904
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<maxlatency> has to be within [%d..%d].\n",
905 906 907 908 909 910 911
		DEFAULT_MAX_TOLERABLE_LATENCY_MINIMUM,
		DEFAULT_MAX_TOLERABLE_LATENCY_MAXIMUM);
    } else if( params->stc == -1
	    && (params->timeoutrecv < DEFAULT_TIMEOUTRECV_MINIMUM  ||
		params->timeoutrecv > DEFAULT_TIMEOUTRECV_MAXIMUM)) {
	if(params->timeoutrecv != 0) {
	    ret = -1;
912
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "<timeoutrecv> has to be within [%d..%d] or equal to zero for not time-out.\n",
913 914 915 916
		    DEFAULT_TIMEOUTRECV_MINIMUM,
		    DEFAULT_TIMEOUTRECV_MAXIMUM);
	}
    } else if( params->stc != -1 && params->max_tolerable_latency > 0 ){
917
	nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY, "<maxlatency> ignored since not defined --stc=-1.\n");
918 919
    } else if(params->stc != -1 && params->timeoutrecv > 0) {
	params->timeoutrecv = 0;
920
	nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY, "<timeoutrecv> ignored since not defined --stc=-1.\n");
921
    }
922

Matteo Quintiliani's avatar
Matteo Quintiliani committed
923
    /*
924
    if( params->stc == -1 ) {
925
	nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY, "<maxlatency> is equal to %d sec.\n", params->max_tolerable_latency);
926
    }
Matteo Quintiliani's avatar
Matteo Quintiliani committed
927
    */
928

929 930
    return ret;
}