-
Notifications
You must be signed in to change notification settings - Fork 79
/
expand.c
70 lines (58 loc) · 1.33 KB
/
expand.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
* Copyright (C) 2023 Yubico AB - See COPYING
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "util.h"
static int buf_write(uint8_t **dst, size_t *size, const void *src, size_t n) {
if (*size < n) {
return -1;
}
memcpy(*dst, src, n);
*dst += n;
*size -= n;
return 0;
}
static int buf_write_byte(uint8_t **dst, size_t *size, uint8_t c) {
return buf_write(dst, size, &c, sizeof(c));
}
static const char *lookup(char var, const char *user) {
switch (var) {
case 'u':
return user;
case '%':
return "%";
default:
// Capture all unknown variables (incl. null byte).
return NULL;
}
}
char *expand_variables(const char *str, const char *user) {
uint8_t *tail, *head;
size_t size = PATH_MAX;
int ok = -1;
if (str == NULL || (tail = head = malloc(size)) == NULL) {
return NULL;
}
for (; *str != '\0'; str++) {
if (*str == '%') {
str++;
const char *value = lookup(*str, user);
if (value == NULL || *value == '\0' ||
buf_write(&head, &size, value, strlen(value)) != 0) {
goto fail;
}
} else if (buf_write_byte(&head, &size, *str) != 0) {
goto fail;
}
}
ok = buf_write_byte(&head, &size, '\0');
fail:
if (ok != 0) {
free(tail);
return NULL;
}
return (char *) tail;
}