ew2mseed fails to open connections to WaveServers in EW 7.10
First reported on Earthworm Forum by Rod Stewart on Apr 1, 2020:
I had a perfectly working earthworm running ew2mseed manually, with this
earthworm 7.9 Ubuntu 18.04 virtual machine running under OSX Parallels
I upgraded to
earthworm 7.10 Ubuntu 19.10 virtual machine running under OSX Parallels
Earthworm installed OK, but I now have network problems when I run ew2mseed.
The waveserver is properly specified in the ew2mseed.d file, and I can ping it. But the log file shows it’s not being read properly from the .d file and says I have a problem with name resolution (see below).
As Rod says, the ew2mseed log file showed a strange entry for the WaveServer name/IP address:
----------------------
WaveServer-0 = nfiguration:16022
-----------------------
The error was introduced in GIT commit 1c1e1d7e, Updating modules to correctly parse/handle IPv6, on July 14, 2016 in ew2mseed_config.c where it parses the WaveServer IP address.
The code where the error occurs is near line 315 in ew2mseed_config.c:
/*5*/ else if( k_its("WaveServer") ) /* Filling WS linked list */
{
rn->wsRing->wsIP = format_IP(k_str()); <=== old code
rn->wsRing->wsIP = k_str(); <=== new code
if (rn->wsRing->wsIP == NULL)
exit(-2);
tmpWord = k_str();
rn->wsRing->wsPort = (char *) calloc(1, strlen(tmpWord) + 1);
strcpy(rn->wsRing->wsPort, tmpWord) ;
rn->WS_num++;
rn->wsRing->next = (struct WS_ring *) calloc(1, sizeof (struct WS_ring ));
rn->wsRing = rn->wsRing->next;
rn->wsRing->wsIP = (char *) NULL;
rn->wsRing->wsPort = (char *) NULL;
rn->wsRing->next = (struct WS_ring *) NULL;
}
The comments for the change are:
** Revision 1.2 2019/01/15 23:15:00 alexander
** Removed use and function 'format_IP()' as addresses are handled by wsAppendMenu
The error is caused by the removal of the call to function format_IP(), which returned a copy of the k_str() value to the caller.
k_str() values are ephemeral. What is missing after the change is code to create a copy of the WaveServer IP address. The new code should have been something like:
/*5*/ else if( k_its("WaveServer") ) /* Filling WS linked list */
{
tmpWord = k_str();
if (tmpWord == NULL)
exit(-2);
rn->wsRing->wsIP = (char *) calloc(1, strlen(tmpWord) + 1);
strcpy(rn->wsRing->wsIP, tmpWord) ;
tmpWord = k_str();
rn->wsRing->wsPort = (char *) calloc(1, strlen(tmpWord) + 1);
strcpy(rn->wsRing->wsPort, tmpWord) ;
rn->WS_num++;
rn->wsRing->next = (struct WS_ring *) calloc(1, sizeof (struct WS_ring ));
rn->wsRing = rn->wsRing->next;
rn->wsRing->wsIP = (char *) NULL;
rn->wsRing->wsPort = (char *) NULL;
rn->wsRing->next = (struct WS_ring *) NULL;
}
Though, even this code is wrong in that it never checks for failed calloc() calls.
This code (from https://stackoverflow.com/questions/252782/strdup-what-does-it-do-in-c) looks safe:
char * strdup(const char * s)
{
size_t len = 1+strlen(s);
char *p = malloc(len);
return p ? memcpy(p, s, len) : (errno = ENOMEM, NULL);
}
From the web page: according to some documents, strdup()
sets errno
to ENOMEM
when allocation fails.