Blame ui/utils.c

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
}