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