/** * expansion.c * * Demonstrates one approach for implementing environment variable expansion in * strings. */ #include #include #include /** * Expands environment variables (identified by $ prefix, e.g., $SHELL) in a * string by resizing and inserting the value of the variable into the string. * This function only does one expansion, but can be called multiple times on a * string to expand more than one variable. * * NOTE: this function allocates memory! The caller is responsible for freeing * the memory. * * Parameters: * - str: The string with variables to expand * * Returns: char pointer to the newly-expanded and allocated string. Returns * NULL if there are no variables to replace or if memory cannot be allocated. */ char *expand_var(char *str) { size_t var_start = 0; var_start = strcspn(str, "$"); if (var_start == strlen(str)) { /* No variable to replace */ return NULL; } size_t var_len = strcspn(str + var_start, " \t\r\n\'\""); char *var_name = malloc(sizeof(char) * var_len + 1); if (var_name == NULL) { return NULL; } strncpy(var_name, str + var_start, var_len); var_name[var_len] = '\0'; if (strlen(var_name) <= 1) { free(var_name); return NULL; } /* Use index 1 to ignore the '$' prefix */ char *value = getenv(&var_name[1]); if (value == NULL) { fprintf(stderr, "value was null\n"); value = ""; } fprintf(stderr, "Replacing variable: %s='%s'\n", var_name, value); free(var_name); /* Grab the size of the remaining string (after the $var): */ size_t remain_sz = strlen(str + var_start + var_len); /* Our final string contains the prefix data, the value of the variable, the * remaining string size, and an extra character for the NUL byte. */ size_t newstr_sz = var_start + strlen(value) + remain_sz + 1; char *newstr = malloc(sizeof(char) * newstr_sz); if (newstr == NULL) { return NULL; } strncpy(newstr, str, var_start); newstr[var_start] = '\0'; strcat(newstr, value); strcat(newstr, str + var_start + var_len); return newstr; }