1
/*
2
 * The MIT License (MIT)
3
 *
4
 * Copyright (c) 2019 Erik Moqvist
5
 *
6
 * Permission is hereby granted, free of charge, to any person
7
 * obtaining a copy of this software and associated documentation
8
 * files (the "Software"), to deal in the Software without
9
 * restriction, including without limitation the rights to use, copy,
10
 * modify, merge, publish, distribute, sublicense, and/or sell copies
11
 * of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be
15
 * included in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
 * SOFTWARE.
25
 *
26
 * This file is part of the humanfriendly project.
27
 */
28

29
#include <stdlib.h>
30
#include <string.h>
31
#include <stdbool.h>
32
#include <stdio.h>
33
#include <errno.h>
34
#include <limits.h>
35
#include <pwd.h>
36
#include "hf.h"
37

38
#define TIME_UNITS_MAX 7
39

40 1
static void hf_null_last(char *buf_p, size_t size)
41
{
42 1
    buf_p[size - 1] = '\0';
43
}
44

45 0
static int char_in_string(char c, const char *str_p)
46
{
47 0
    while (*str_p != '\0') {
48 0
        if (c == *str_p) {
49 0
            return (1);
50
        }
51

52 0
        str_p++;
53
    }
54

55 0
    return (0);
56
}
57

58 1
char *hf_get_username(char *buf_p, size_t size, const char *default_p)
59
{
60
    char *res_p;
61
    struct passwd *passwd_p;
62

63 1
    res_p = buf_p;
64 1
    passwd_p = getpwuid(geteuid());
65

66 1
    if (passwd_p == NULL) {
67 1
        if (default_p == NULL) {
68 1
            res_p = NULL;
69
        } else {
70 1
            strncpy(buf_p, default_p, size);
71
        }
72
    } else {
73 1
        strncpy(buf_p, passwd_p->pw_name, size);
74

75 1
        if (size > 0) {
76 1
            hf_null_last(buf_p, size);
77
        }
78
    }
79

80 1
    hf_null_last(buf_p, size);
81

82 1
    return (res_p);
83
}
84

85 1
char *hf_get_hostname(char *buf_p, size_t size, const char *default_p)
86
{
87
    int res;
88
    char *res_p;
89

90 1
    res_p = buf_p;
91 1
    res = gethostname(buf_p, size);
92

93 1
    if (res != 0) {
94 1
        if (default_p == NULL) {
95 1
            res_p = NULL;
96
        } else {
97 1
            strncpy(buf_p, default_p, size);
98
        }
99
    }
100

101 1
    hf_null_last(buf_p, size);
102

103 1
    return (res_p);
104
}
105

106
/* Common time units, used for formatting of time spans. */
107
struct time_unit_t {
108
    unsigned long divider;
109
    const char *unit_p;
110
};
111

112
static struct time_unit_t time_units[TIME_UNITS_MAX] = {
113
    {
114
        .divider = 60 * 60 * 24 * 7 * 52 * 1000ul,
115
        .unit_p = "y"
116
    },
117
    {
118
        .divider = 60 * 60 * 24 * 7 * 1000ul,
119
        .unit_p = "w"
120
    },
121
    {
122
        .divider = 60 * 60 * 24 * 1000ul,
123
        .unit_p = "d"
124
    },
125
    {
126
        .divider = 60 * 60 * 1000ul,
127
        .unit_p = "h"
128
    },
129
    {
130
        .divider = 60 * 1000ul,
131
        .unit_p = "m"
132
    },
133
    {
134
        .divider = 1000ul,
135
        .unit_p = "s"
136
    },
137
    {
138
        .divider = 1ul,
139
        .unit_p = "ms"
140
    }
141
};
142

143 1
static const char *get_delimiter(bool is_first, bool is_last)
144
{
145 1
    if (is_first) {
146 1
        return ("");
147 1
    } else if (is_last) {
148 1
        return (" and ");
149
    } else {
150 1
        return (", ");
151
    }
152
}
153

154 1
char *hf_format_timespan(char *buf_p,
155
                         size_t size,
156
                         unsigned long long timespan_ms)
157
{
158
    int i;
159
    int res;
160
    unsigned long long count;
161
    size_t offset;
162

163 1
    strncpy(buf_p, "", size);
164 1
    offset = 0;
165

166 1
    for (i = 0; i < TIME_UNITS_MAX; i++) {
167 1
        count = (timespan_ms / time_units[i].divider);
168 1
        timespan_ms -= (count * time_units[i].divider);
169

170 1
        if (count == 0) {
171 1
            continue;
172
        }
173

174 1
        res = snprintf(&buf_p[offset],
175
                       size - offset,
176
                       "%s%llu%s",
177 1
                       get_delimiter(strlen(buf_p) == 0, timespan_ms == 0),
178
                       count,
179
                       time_units[i].unit_p);
180 1
        hf_null_last(buf_p, size);
181

182 1
        if (res > 0) {
183 1
            offset += (size_t)res;
184
        }
185
    }
186

187 1
    if (strlen(buf_p) == 0) {
188 1
        strncpy(buf_p, "0s", size);
189 1
        hf_null_last(buf_p, size);
190
    }
191

192 1
    return (buf_p);
193
}
194

195 1
long hf_string_to_long(const char *string_p,
196
                       long minimum,
197
                       long maximum,
198
                       long default_value,
199
                       int base)
200
{
201
    long value;
202
    char *end_p;
203

204 1
    errno = 0;
205 1
    value = strtol(string_p, &end_p, base);
206

207 1
    if ((errno != 0) && (value == 0)) {
208 0
        value = default_value;
209 1
    } else if (end_p == string_p) {
210 1
        value = default_value;
211 1
    } else if (*end_p != '\0') {
212 1
        value = default_value;
213
    }
214

215 1
    if (value < minimum) {
216 1
        value = minimum;
217
    }
218

219 1
    if (value > maximum) {
220 1
        value = maximum;
221
    }
222

223 1
    return (value);
224
}
225

226 1
char *hf_buffer_to_string(char *dst_p,
227
                          size_t dst_size,
228
                          const void *src_p,
229
                          size_t src_size)
230
{
231 1
    if (src_size > 0) {
232 1
        if (src_size > (dst_size - 1)) {
233 1
            src_size = (dst_size - 1);
234
        }
235

236 1
        memcpy(dst_p, src_p, src_size);
237
    }
238

239 1
    dst_p[src_size] = '\0';
240

241 1
    return (dst_p);
242
}
243

244 0
char *hf_strip(char *str_p, const char *strip_p)
245
{
246
    char *begin_p;
247
    size_t length;
248

249
    /* Strip whitespace characters by default. */
250 0
    if (strip_p == NULL) {
251 0
        strip_p = "\t\n\x0b\x0c\r ";
252
    }
253

254
    /* String leading characters. */
255 0
    while ((*str_p != '\0') && char_in_string(*str_p, strip_p)) {
256 0
        str_p++;
257
    }
258

259 0
    begin_p = str_p;
260

261
    /* Strip training characters. */
262 0
    length = strlen(str_p);
263 0
    str_p += (length - 1);
264

265 0
    while ((str_p >= begin_p) && char_in_string(*str_p, strip_p)) {
266 0
        *str_p = '\0';
267 0
        str_p--;
268
    }
269

270 0
    return (begin_p);
271
}
272

273 1
void *hf_file_read_all(const char *path_p, size_t *size_p)
274
{
275
    FILE *file_p;
276
    void *buf_p;
277
    long file_size;
278

279 1
    file_p = fopen(path_p, "rb");
280

281 1
    if (file_p == NULL) {
282 1
        return (NULL);
283
    }
284

285 1
    if (fseek(file_p, 0, SEEK_END) != 0) {
286 0
        goto out1;
287
    }
288

289 1
    file_size = ftell(file_p);
290

291 1
    if (file_size == -1) {
292 0
        goto out1;
293
    }
294

295 1
    if (size_p != NULL) {
296 1
        *size_p = (size_t)file_size;
297
    }
298

299 1
    if (file_size > 0) {
300 1
        buf_p = malloc((size_t)file_size);
301

302 1
        if (buf_p == NULL) {
303 0
            goto out1;
304
        }
305

306 1
        if (fseek(file_p, 0, SEEK_SET) != 0) {
307 0
            goto out2;
308
        }
309

310 1
        if (fread(buf_p, (size_t)file_size, 1, file_p) != 1) {
311 1
            goto out2;
312
        }
313
    } else {
314 1
        buf_p = malloc(1);
315
    }
316

317 1
    fclose(file_p);
318

319 1
    return (buf_p);
320

321
 out2:
322 1
    free(buf_p);
323

324
 out1:
325 1
    fclose(file_p);
326

327 1
    return (NULL);
328
}

Read our documentation on viewing source code .

Loading