nmxptool_getoptlong.c 29.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.80 2008-03-07 10:35:23 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\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
72
        (Private Data Stream 1.4, Data Access Protocol 1.0)\n",
73 74 75 76
	NMXP_LOG_STR(PACKAGE_NAME), NMXP_LOG_STR(PACKAGE_VERSION), NMXP_LOG_STR(PACKAGE_BUILD)
	/*
	, nmxp_log_version()	
	*/
77
	);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
78 79

    nmxptool_supports();
80 81
}

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

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

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

107

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

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

#ifdef HAVE_EARTHWORMOBJS
135
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
136
       %s nmxptool.d\n\
137
             Launched as Earthworm module to redirect data into the EW-Rings.\n\
138
\n", NMXP_LOG_STR(PACKAGE_NAME));
139 140 141 142 143 144
#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\
145
\n", NMXP_LOG_STR(PACKAGE_NAME));
Matteo Quintiliani's avatar
Matteo Quintiliani committed
146 147
#endif

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

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

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

261
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
262
Other arguments:\n\
263
  -N, --network=NET       Default output Network code. (default '%s').\n\
264
  -n, --location=LOC      Default output Location code. DISABLED!\n\
265
  -v, --verbose=level     Be verbose. level is a bitmap:\n\
266
                          %d Channel State, %d Channel, %d Raw Stream,\n\
267 268 269
                          %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
270
  -g, --logdata           Print info about packet data.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
271
  -G, --logsample         Print sample values of packets. Includes -g.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
272
",
273
	    NMXP_LOG_STR(DEFAULT_NETWORK),
274
	    NMXP_LOG_D_CHANSTATE,
275 276 277 278 279 280 281 282 283 284
	    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
285 286 287
		);

#ifdef HAVE_LIBMSEED
288
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
289 290
  -m, --writeseed         Pack received data in Mini-SEED records\n\
                          and write to a file.\n");
291 292
#endif

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

296
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
297
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
298
  -k, --slink=pluginid    Send received data to SeedLink as a plug-in.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
299
                          THIS OPTION, INSIDE THE FILE seedlink.ini, MUST BE\n\
300 301
                          THE LAST WITHOUT ADDING VALUE FOR pluginid!\n\
                          pluginid is set by SeisComP daemon.\n");
302
#endif
303

304
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "\
305
  -V, --version           Print tool version.\n\
306
  -h, --help              Print this help.\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
307 308
\n");

309
    nmxptool_author_support();
310 311 312 313 314

    /*
    if(long_options) {
	int i=0;
	while(long_options[i].name) {
315 316 317
	    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);
318 319 320 321 322 323 324
	    i++;
	}
    }
    */
}


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 357 358 359 360 361 362 363 364
#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;
}

365
int nmxptool_getopt_long(int argc, char **argv, NMXPTOOL_PARAMS *params)
366
{
367 368
    int ret_errors = 0;

369
    NMXP_TM_T tmp_tmt;
370 371 372 373
    int i;
    char one_time_option[255];
    int c;

374 375 376 377
    int len_int, j;
    char unit = 'X';
    char str_interval[100];

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

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

Matteo Quintiliani's avatar
Matteo Quintiliani committed
427 428 429
    int option_index = 0;


430 431 432
#ifdef HAVE_LIBMSEED
    strcat(optstr, "m");
#endif
433

434 435 436
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
    strcat(optstr, "k:");
#endif
437 438 439 440 441 442 443 444 445 446


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

449 450 451 452 453 454 455 456 457 458 459 460 461 462
    /* 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;
		}
	    }
	}
    }

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

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

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

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

		case 'C':
499
		    if(params->channels) {
500 501
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Channels have been already defined by State File (option -F)!\n");
502 503 504 505
			ret_errors++;
		    } else {
			params->channels = optarg;
		    }
506 507 508 509 510 511
		    break;

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

512
		case 'n':
513 514 515 516 517
		    if(1) {
			nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY, "Location is currently disabled!\n");
		    } else {
			params->location = optarg;
		    }
518 519
		    break;

520 521
		case 'S':
		    params->stc = atoi(optarg);
522
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Short-Term-Completion %d.\n", params->stc);
523 524 525 526 527 528
		    break;

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

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

		case 'e':
539
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
540
			/* MESSAGE ERROR */
Matteo Quintiliani's avatar
Matteo Quintiliani committed
541
			ret_errors++;
542
		    } else {
543
			params->end_time = nmxp_data_tm_to_time(&tmp_tmt);
544 545 546
		    }
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
547
		case 't':
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
		    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
592 593
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
594 595 596 597
		case 'd':
		    params->delay = atoi(optarg);
		    break;

598 599 600 601 602 603 604 605
		case 'u':
		    params->datas_username = optarg;
		    break;

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

606
		case 'M':
Matteo Quintiliani's avatar
Matteo Quintiliani committed
607
		    params->max_tolerable_latency = atoi(optarg);
608 609
		    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
610 611
		    break;

612
		case 'T':
613
		    params->timeoutrecv = atoi(optarg);
614 615
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Time-out receiving %d\n",
			    params->timeoutrecv);
616 617
		    break;

618 619 620 621
		case 'v':
		    params->verbose_level = atoi(optarg);
		    break;

622 623 624
		case 'B':
		    params->flag_buffered = 1;
		    if(nmxp_data_parse_date(optarg, &tmp_tmt) == -1) {
625
			/* MESSAGE ERROR */
626 627 628 629 630 631
			ret_errors++;
		    } else {
			params->buffered_time = nmxp_data_tm_to_time(&tmp_tmt);
		    }
		    break;

632 633
		case 'A':
		    if(optarg) {
634
			params->max_data_to_retrieve = atoi(optarg);
635
		    }
636
		    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "Max_time_to_retrieve %d\n", params->max_data_to_retrieve);
637
		    break;
638

639 640 641 642 643 644 645
#ifdef HAVE___SRC_SEEDLINK_PLUGIN_C
		case 'k':
		    params->flag_slink = 1;
		    params->plugin_slink = optarg;
		    break;
#endif

646
		case 'F':
647
		    params->flag_buffered = 1;
648
		    params->statefile = optarg;
649 650 651 652 653 654
		    if(params->channels == NULL) {
			params->channels = get_channel_list_argument_from_state_file(params->statefile);
			if(params->channels) {
			    /* Do nothing */
			} else {
			    ret_errors++;
655 656
			    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));
657
			}
658 659
		    } else {
			ret_errors++;
660 661
			nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY,
				"Channels have been already defined by option -C!\n");
662 663 664
		    }
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
665
		case 'g':
666 667 668
		    params->flag_logdata = 1;
		    break;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
669
		case 'G':
Matteo Quintiliani's avatar
Matteo Quintiliani committed
670
		    params->flag_logdata = 1;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
671 672 673
		    params->flag_logsample = 1;
		    break;

674
		case 'b':
675
		    params->flag_buffered = 1;
676 677
		    break;

678 679 680 681
		case 'l':
		    params->flag_listchannels = 1;
		    break;

682 683 684 685
		case 'L':
		    params->flag_listchannelsnaqs = 1;
		    break;

686 687 688 689
		case 'i':
		    params->flag_request_channelinfo = 1;
		    break;

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
#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;

705 706
		case 'V':
		    nmxptool_version();
Matteo Quintiliani's avatar
Matteo Quintiliani committed
707
		    nmxptool_author_support();
708 709 710
		    exit (1);
		    break;

711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
		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;

728
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "non-option ARGV-elements: ");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
729 730
	while (optind < argc) {
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%s ",
731 732
		    NMXP_LOG_STR(argv[optind]));
	    optind++;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
733
	}
734 735 736 737 738 739 740
	putchar ('\n');
    }

    return ret_errors;
}


741 742 743 744 745
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\
746
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
747
    NMXP_LOG_STR(params->hostname),
748 749 750 751 752
    params->portnumberdap,
    params->portnumberpds
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
753
    char *channels: %s\n\
754
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
755
    NMXP_LOG_STR(params->channels)
756 757 758
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
759 760 761 762 763
    char *network: %s\n\
    char *location: %s\n\
    double start_time: %f\n\
    double end_time: %f\n\
    int32_t interval: %d\n\
764
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
765 766
    NMXP_LOG_STR(params->network),
    NMXP_LOG_STR(params->location),
767 768 769 770 771 772 773
    params->start_time,
    params->end_time,
    params->interval
);


    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
774 775
    char *datas_username: %s\n\
    char *datas_password: %s\n\
776
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
777 778
    NMXP_LOG_STR(params->datas_username),
    NMXP_LOG_STR(params->datas_password)
779 780 781
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
782 783 784 785 786 787 788
    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\
789 790 791
",
    params->stc,
    params->rate,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
792
    NMXP_LOG_STR(params->plugin_slink),
793 794 795 796 797 798 799
    params->delay,
    params->max_tolerable_latency,
    params->timeoutrecv,
    params->verbose_level
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
800 801
    char *ew_configuration_file: %s\n\
    char *statefile: %s\n\
Matteo Quintiliani's avatar
Matteo Quintiliani committed
802
    int32_t max_data_to_retrieve: %d\n\
803
",
Matteo Quintiliani's avatar
Matteo Quintiliani committed
804 805
    NMXP_LOG_STR(params->ew_configuration_file),
    NMXP_LOG_STR(params->statefile),
Matteo Quintiliani's avatar
Matteo Quintiliani committed
806
    params->max_data_to_retrieve
807 808 809
);

    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_EXTRA, "\
810 811 812 813 814 815 816 817 818
    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
819
    int flag_logsample: %d\n\
820 821 822 823 824 825 826 827 828
",
    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
829 830
    params->flag_logdata,
    params->flag_logsample
831 832 833
    );
}

834 835


836
int nmxptool_check_params(NMXPTOOL_PARAMS *params) {
837 838
    int ret = 0;

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

Matteo Quintiliani's avatar
Matteo Quintiliani committed
931
    /*
932
    if( params->stc == -1 ) {
933
	nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY, "<maxlatency> is equal to %d sec.\n", params->max_tolerable_latency);
934
    }
Matteo Quintiliani's avatar
Matteo Quintiliani committed
935
    */
936

937 938
    return ret;
}