Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Expand environment variables in text (bash style)
- * @author gocha <http://twitter.com/gochaism> (I release it into public domain, though)
- * FYI: Windows have ExpandEnvironmentStrings function for a similar purpose.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <ctype.h>
- #ifdef HAVE_STDBOOL_H
- # include <stdbool.h>
- #else
- # ifndef HAVE__BOOL
- # ifdef __cplusplus
- typedef bool _Bool;
- # else
- # define _Bool signed char
- # endif
- # endif
- # define bool _Bool
- # define false 0
- # define true 1
- # define __bool_true_false_are_defined 1
- #endif
- /**
- * Expand environment variables in a string (bash style)
- * @param str Input path string.
- * @param outputStr Output path string buffer.
- * @param bufferSize Size of the output buffer in chars. (includes null character)
- * @return Number of characters written to the buffer (excludes null character). Returns -1 if a fatal error occurred.
- */
- int ExpandEnvironmentVariables(const char *str, char *outputStr, int bufferSize)
- {
- int inIndex = 0;
- int outIndex = 0;
- int varStartIndex = -1;
- bool isInVariable = false;
- bool hasParenthesis = false;
- char *varName = NULL;
- char *varValue = NULL;
- int varNameLength = 0;
- int varValueLength = 0;
- unsigned char cIn, cNext;
- do
- {
- // check output buffer size
- if (outIndex >= bufferSize)
- {
- outputStr[bufferSize - 1] = '\0';
- outIndex = bufferSize + 1;
- break;
- }
- // read a character
- cIn = (unsigned char) str[inIndex];
- cNext = (cIn != '\0') ? (unsigned char) str[inIndex + 1] : '\0';
- if (isInVariable)
- {
- // check if we are still in a variable
- if (hasParenthesis)
- {
- isInVariable = (cIn != '}');
- if (cIn == '\0')
- {
- fprintf(stderr, "error: missing closing parenthesis.\n");
- outputStr[outIndex] = '\0';
- return -1;
- }
- else if (cIn == '{')
- {
- fprintf(stderr, "error: bad substitution.\n");
- outputStr[outIndex] = '\0';
- return -1;
- }
- }
- else
- {
- // check for the pattern [0-9]+|[A-Za-z_][0-9A-Za-z_]*
- if ((isdigit(str[varStartIndex]) != 0))
- {
- isInVariable = (isdigit(cIn) != 0);
- }
- else
- {
- isInVariable = ((isalnum(cIn) != 0) || cIn == '_');
- }
- }
- // reached to end of variable
- if (!isInVariable)
- {
- // get variable name
- varNameLength = inIndex - varStartIndex;
- varName = (char*) malloc(varNameLength + 1);
- memcpy(varName, &str[varStartIndex], varNameLength);
- varName[varNameLength] = '\0';
- if (varName[0] != '\0')
- {
- // expand a variable
- varValue = getenv(varName);
- if (varValue != NULL)
- {
- varValueLength = strlen(varValue);
- if (outIndex + varValueLength <= bufferSize)
- {
- memcpy(&outputStr[outIndex], varValue, varValueLength);
- outIndex += varValueLength;
- }
- else
- {
- memcpy(&outputStr[outIndex], varValue, bufferSize - outIndex);
- outIndex = bufferSize;
- }
- if (outIndex == bufferSize)
- {
- outputStr[bufferSize - 1] = '\0';
- outIndex = bufferSize + 1;
- break;
- }
- }
- else
- {
- fprintf(stderr, "error: ${%s} is not defined.\n", varName);
- outputStr[outIndex] = '\0';
- return -1;
- }
- if (!hasParenthesis)
- {
- // redo the same character
- inIndex--;
- continue;
- }
- }
- else
- {
- // not a variable
- if (hasParenthesis)
- {
- fprintf(stderr, "error: variable name must not be empty.\n");
- outputStr[outIndex] = '\0';
- return -1;
- }
- else
- {
- outputStr[outIndex] = '$';
- outIndex++;
- if (outIndex < bufferSize)
- {
- outputStr[outIndex] = cIn;
- outIndex++;
- }
- }
- }
- }
- }
- else
- {
- if (cIn == '$')
- {
- // start of a variable
- isInVariable = true;
- // check if it has a parenthesis
- if (cNext == '{')
- {
- hasParenthesis = true;
- inIndex++;
- }
- else
- {
- hasParenthesis = false;
- }
- varStartIndex = inIndex + 1;
- }
- else
- {
- // plain string
- outputStr[outIndex] = cIn;
- outIndex++;
- }
- }
- #ifdef MS932_SUPPORT
- // check for the lead-byte of MS932 (Windows-31J)
- if ((cIn >= 0x81 && cIn <= 0x9f) || (cIn >= 0xe0 && cIn <= 0xfc))
- {
- // check for the trailer-byte as well
- if ((cNext >= 0x40 && cNext <= 0x7e) || (cNext >= 0x80 && cNext <= 0xfc))
- {
- if (!isInVariable)
- {
- if (outIndex + 1 < bufferSize)
- {
- outputStr[outIndex] = cNext;
- }
- else
- {
- outputStr[outIndex - 1] = '\0';
- }
- outIndex++;
- }
- inIndex++;
- }
- }
- #endif
- } while (str[inIndex++] != '\0');
- return outIndex - 1;
- }
- // test routine
- int main(int argc, char *argv[])
- {
- char s[4096];
- char *pat;
- int ret;
- pat = "HOME";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "$HOME";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "${HOME}";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "${HOME!}";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "$HOME!";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "$HOME$HOME";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "$123ABC";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "$";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "${";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "${{";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "$}";
- ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "$NOT_DEFINED";
- ret = ExpandEnvironmentVariables(pat, s, 8);
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- pat = "ABCDEFG$HOME";
- ret = ExpandEnvironmentVariables(pat, s, 8);
- printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement