1/* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "EnvironmentUtilities.h" 28 29#include <wtf/text/CString.h> 30 31namespace WebKit { 32 33namespace EnvironmentUtilities { 34 35void stripValuesEndingWithString(const char* environmentVariable, const char* searchValue) 36{ 37 ASSERT(environmentVariable); 38 ASSERT(searchValue); 39 40 // Grab the current value of the environment variable. 41 char* environmentValue = getenv(environmentVariable); 42 43 if (!environmentValue || environmentValue[0] == '\0') 44 return; 45 46 // Set up the strings we'll be searching for. 47 size_t searchLength = strlen(searchValue); 48 if (!searchLength) 49 return; 50 51 Vector<char> searchValueWithColonVector; 52 searchValueWithColonVector.grow(searchLength + 2); 53 char* searchValueWithColon = searchValueWithColonVector.data(); 54 size_t searchLengthWithColon = searchLength + 1; 55 56 memcpy(searchValueWithColon, searchValue, searchLength); 57 searchValueWithColon[searchLength] = ':'; 58 searchValueWithColon[searchLengthWithColon] = '\0'; 59 60 // Loop over environmentValueBuffer, removing any components that match the search value ending with a colon. 61 char* componentStart = environmentValue; 62 char* match = strstr(componentStart, searchValueWithColon); 63 bool foundAnyMatches = match != NULL; 64 while (match != NULL) { 65 // Update componentStart to point to the colon immediately preceding the match. 66 char* nextColon = strstr(componentStart, ":"); 67 while (nextColon && nextColon < match) { 68 componentStart = nextColon; 69 nextColon = strstr(componentStart + 1, ":"); 70 } 71 72 // Copy over everything right of the match to the current component start, and search from there again. 73 if (componentStart[0] == ':') { 74 // If componentStart points to a colon, go ahead and copy the colon over. 75 strcpy(componentStart, match + searchLength); 76 } else { 77 // Otherwise, componentStart still points to the beginning of environmentValueBuffer, so don't copy over the colon. 78 // The edge case is if the colon is the last character in the string, so "match + searchLengthWithoutColon + 1" is the 79 // null terminator of the original input, in which case this is still safe. 80 strcpy(componentStart, match + searchLengthWithColon); 81 } 82 83 match = strstr(componentStart, searchValueWithColon); 84 } 85 86 // Search for the value without a trailing colon, seeing if the original input ends with it. 87 match = strstr(componentStart, searchValue); 88 while (match != NULL) { 89 if (match[searchLength] == '\0') 90 break; 91 match = strstr(match + 1, searchValue); 92 } 93 94 // Since the original input ends with the search, strip out the last component. 95 if (match) { 96 // Update componentStart to point to the colon immediately preceding the match. 97 char* nextColon = strstr(componentStart, ":"); 98 while (nextColon && nextColon < match) { 99 componentStart = nextColon; 100 nextColon = strstr(componentStart + 1, ":"); 101 } 102 103 // Whether componentStart points to the original string or the last colon, putting the null terminator there will get us the desired result. 104 componentStart[0] = '\0'; 105 106 foundAnyMatches = true; 107 } 108 109 // If we found no matches, don't change anything. 110 if (!foundAnyMatches) 111 return; 112 113 // If we have nothing left, just unset the variable 114 if (environmentValue[0] == '\0') { 115 unsetenv(environmentVariable); 116 return; 117 } 118 119 setenv(environmentVariable, environmentValue, 1); 120} 121 122} // namespace EnvironmentUtilities 123 124} // namespace WebKit 125