/*
* 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, (uint8_t)*str) != 0) {
goto fail;
}
}
ok = buf_write_byte(&head, &size, '\0');
fail:
if (ok != 0) {
free(tail);
return NULL;
}
return (char *) tail;
}