|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
mtr -- a network diagnostic tool
|
|
Packit |
b802ec |
Copyright (C) 1997,1998 Matt Kimball
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
b802ec |
it under the terms of the GNU General Public License version 2 as
|
|
Packit |
b802ec |
published by the Free Software Foundation.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is distributed in the hope that it will be useful,
|
|
Packit |
b802ec |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b802ec |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
b802ec |
GNU General Public License for more details.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
You should have received a copy of the GNU General Public License
|
|
Packit |
b802ec |
along with this program; if not, write to the Free Software
|
|
Packit |
b802ec |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "config.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include <ctype.h>
|
|
Packit |
b802ec |
#include <errno.h>
|
|
Packit |
b802ec |
#include <limits.h>
|
|
Packit |
b802ec |
#include <stdint.h>
|
|
Packit |
b802ec |
#include <stdio.h>
|
|
Packit |
b802ec |
#include <stdlib.h>
|
|
Packit |
b802ec |
#include <string.h>
|
|
Packit |
b802ec |
#include <time.h>
|
|
Packit |
b802ec |
#include <unistd.h>
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef HAVE_ERROR_H
|
|
Packit |
b802ec |
#include <error.h>
|
|
Packit |
b802ec |
#else
|
|
Packit |
b802ec |
#include "portability/error.h"
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef HAVE_STDIO_EXT_H
|
|
Packit |
b802ec |
#include <stdio_ext.h>
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "utils.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
char *trim(
|
|
Packit |
b802ec |
char *str,
|
|
Packit |
b802ec |
const char c)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
char *p = str;
|
|
Packit |
b802ec |
size_t len;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* left trim */
|
|
Packit |
b802ec |
while (*p && (isspace((unsigned char) *p) || (c && *p == c)))
|
|
Packit |
b802ec |
p++;
|
|
Packit |
b802ec |
if (str < p) {
|
|
Packit |
b802ec |
len = strlen(str);
|
|
Packit |
b802ec |
memmove(str, p, len + 1);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* right trim */
|
|
Packit |
b802ec |
len = strlen(str);
|
|
Packit |
b802ec |
while (len) {
|
|
Packit |
b802ec |
len--;
|
|
Packit |
b802ec |
if (isspace((unsigned char) str[len]) || (c && str[len] == c)) {
|
|
Packit |
b802ec |
continue;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
len++;
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
str[len] = '\0';
|
|
Packit |
b802ec |
return str;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Parse string, and return positive signed int. */
|
|
Packit |
b802ec |
int strtonum_or_err(
|
|
Packit |
b802ec |
const char *str,
|
|
Packit |
b802ec |
const char *errmesg,
|
|
Packit |
b802ec |
const int type)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
unsigned long int num;
|
|
Packit |
b802ec |
char *end = NULL;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (str != NULL && *str != '\0') {
|
|
Packit |
b802ec |
errno = 0;
|
|
Packit |
b802ec |
num = strtoul(str, &end, 10);
|
|
Packit |
b802ec |
if (errno == 0 && str != end && end != NULL && *end == '\0') {
|
|
Packit |
b802ec |
switch (type) {
|
|
Packit |
b802ec |
case STRTO_INT:
|
|
Packit |
b802ec |
if (num < INT_MAX)
|
|
Packit |
b802ec |
return num;
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
case STRTO_U32INT:
|
|
Packit |
b802ec |
if (num < UINT32_MAX)
|
|
Packit |
b802ec |
return num;
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
float strtofloat_or_err(
|
|
Packit |
b802ec |
const char *str,
|
|
Packit |
b802ec |
const char *errmesg)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
double num;
|
|
Packit |
b802ec |
char *end = NULL;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (str != NULL && *str != '\0') {
|
|
Packit |
b802ec |
errno = 0;
|
|
Packit |
b802ec |
num = strtod(str, &end;;
|
|
Packit |
b802ec |
if (errno == 0 && str != end && end != NULL && *end == '\0'
|
|
Packit |
b802ec |
#ifdef FLT_MAX
|
|
Packit |
b802ec |
&& num < FLT_MAX
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
)
|
|
Packit |
b802ec |
return num;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void *xmalloc(
|
|
Packit |
b802ec |
const size_t size)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
void *ret = malloc(size);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (!ret && size)
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "cannot allocate %zu bytes", size);
|
|
Packit |
b802ec |
return ret;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
char *xstrdup(
|
|
Packit |
b802ec |
const char *str)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
char *ret;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (!str)
|
|
Packit |
b802ec |
return NULL;
|
|
Packit |
b802ec |
ret = strdup(str);
|
|
Packit |
b802ec |
if (!ret)
|
|
Packit |
b802ec |
error(EXIT_FAILURE, errno, "cannot duplicate string: %s", str);
|
|
Packit |
b802ec |
return ret;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifndef HAVE___FPENDING
|
|
Packit |
b802ec |
static inline int __fpending(
|
|
Packit |
b802ec |
FILE * stream __attribute__ ((__unused__)))
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
static inline int close_stream(
|
|
Packit |
b802ec |
FILE * stream)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
const int some_pending = (__fpending(stream) != 0);
|
|
Packit |
b802ec |
const int prev_fail = (ferror(stream) != 0);
|
|
Packit |
b802ec |
const int fclose_fail = (fclose(stream) != 0);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) {
|
|
Packit |
b802ec |
if (!fclose_fail && !(errno == EPIPE))
|
|
Packit |
b802ec |
errno = 0;
|
|
Packit |
b802ec |
return EOF;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Meant to be used atexit(close_stdout); */
|
|
Packit |
b802ec |
void close_stdout(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if (close_stream(stdout) != 0 && !(errno == EPIPE)) {
|
|
Packit |
b802ec |
error(0, errno, "write error");
|
|
Packit |
b802ec |
_exit(EXIT_FAILURE);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
if (close_stream(stderr) != 0)
|
|
Packit |
b802ec |
_exit(EXIT_FAILURE);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* ctime() replacement that will reteturn ISO-8601 timestamp string such as:
|
|
Packit |
b802ec |
* 2016-08-29T19:25:02+01:00 */
|
|
Packit |
b802ec |
const char *iso_time(
|
|
Packit |
b802ec |
const time_t * t)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
static char s[32];
|
|
Packit |
b802ec |
struct tm *tm;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
tm = localtime(t);
|
|
Packit |
b802ec |
strftime(s, sizeof(s), "%Y-%m-%dT%H:%M:%S%z", tm);
|
|
Packit |
b802ec |
return s;
|
|
Packit |
b802ec |
}
|