static Unicode UnicodeTrimInternal(ConstUnicode str, // IN UnicodeTrimSide side) // IN { Unicode trimmed; utf16_t *utf16; utf16_t *utf16Start; utf16_t *utf16End; ASSERT(str); utf16 = Unicode_GetAllocBytes(str, STRING_ENCODING_UTF16); utf16Start = utf16; utf16End = utf16 + Unicode_UTF16Strlen(utf16); if (side & UNICODE_TRIMLEFT) { while (utf16Start != utf16End && UnicodeSimpleIsWhiteSpace(*utf16Start)) { utf16Start++; } } if (side & UNICODE_TRIMRIGHT) { while (utf16End != utf16Start && UnicodeSimpleIsWhiteSpace(*(utf16End - 1))) { utf16End--; } } *utf16End = 0; trimmed = Unicode_AllocWithUTF16(utf16Start); free(utf16); return trimmed; }
Unicode Unicode_FoldCase(ConstUnicode str) // IN { Unicode folded; utf16_t *utf16; utf16_t *utf16Current; ASSERT(str); utf16 = Unicode_GetAllocBytes(str, STRING_ENCODING_UTF16); utf16Current = utf16; while (*utf16Current) { *utf16Current = UnicodeSimpleCaseFold(*utf16Current); utf16Current++; } folded = Unicode_AllocWithUTF16(utf16); free(utf16); return folded; }
Unicode File_StripSlashes(ConstUnicode path) // IN: { Unicode result, volume, dir, base; /* * SplitName handles all drive letter/UNC/whatever cases, all we * have to do is make sure the dir part is stripped of slashes if * there isn't a base part. */ File_SplitName(path, &volume, &dir, &base); if (!Unicode_IsEmpty(dir) && Unicode_IsEmpty(base)) { char *dir2 = Unicode_GetAllocBytes(dir, STRING_ENCODING_UTF8); size_t i = strlen(dir2); /* * Don't strip first slash on Windows, since we want at least * one slash to trail a drive letter/colon or UNC specifier. */ #if defined(_WIN32) while ((i > 1) && (('/' == dir2[i - 1]) || ('\\' == dir2[i - 1]))) { #else while ((i > 0) && ('/' == dir2[i - 1])) { #endif i--; } Unicode_Free(dir); dir = Unicode_AllocWithLength(dir2, i, STRING_ENCODING_UTF8); free(dir2); } result = Unicode_Join(volume, dir, base, NULL); Unicode_Free(volume); Unicode_Free(dir); Unicode_Free(base); return result; } /* *----------------------------------------------------------------------------- * * File_MapPathPrefix -- * * Given a path and a newPrefix -> oldPrefix mapping, transform * oldPath according to the mapping. * * Results: * The new path, or NULL if there is no mapping. * * Side effects: * The returned string is allocated, free it. * *----------------------------------------------------------------------------- */ char * File_MapPathPrefix(const char *oldPath, // IN: const char **oldPrefixes, // IN: const char **newPrefixes, // IN: size_t numPrefixes) // IN: { int i; size_t oldPathLen = strlen(oldPath); for (i = 0; i < numPrefixes; i++) { char *newPath; char *oldPrefix; char *newPrefix; size_t oldPrefixLen; oldPrefix = File_StripSlashes(oldPrefixes[i]); newPrefix = File_StripSlashes(newPrefixes[i]); oldPrefixLen = strlen(oldPrefix); /* * If the prefix matches on a DIRSEPS boundary, or the prefix is the * whole string, replace it. * * If we don't insist on matching a whole directory name, we could * mess things of if one directory is a substring of another. * * Perform a case-insensitive compare on Windows. (There are * case-insensitive filesystems on MacOS also, but the problem * is more acute with Windows because of frequent drive-letter * case mismatches. So in lieu of actually asking the * filesystem, let's just go with a simple ifdef for now.) */ if ((oldPathLen >= oldPrefixLen) && #ifdef _WIN32 (Str_Strncasecmp(oldPath, oldPrefix, oldPrefixLen) == 0) && #else (Str_Strncmp(oldPath, oldPrefix, oldPrefixLen) == 0) && #endif (strchr(VALID_DIRSEPS, oldPath[oldPrefixLen]) || (oldPath[oldPrefixLen] == '\0'))) { size_t newPrefixLen = strlen(newPrefix); size_t newPathLen = (oldPathLen - oldPrefixLen) + newPrefixLen; ASSERT(newPathLen > 0); ASSERT(oldPathLen >= oldPrefixLen); newPath = Util_SafeMalloc((newPathLen + 1) * sizeof(char)); memcpy(newPath, newPrefix, newPrefixLen); memcpy(newPath + newPrefixLen, oldPath + oldPrefixLen, oldPathLen - oldPrefixLen + 1); /* * It should only match once. Weird self-referencing mappings * aren't allowed. */ free(oldPrefix); free(newPrefix); return newPath; } free(oldPrefix); free(newPrefix); } return NULL; }
Bool ProcMgr_ImpersonateUserStart(const char *user, // IN: UTF-8 encoded user name AuthToken token) // IN { char buffer[BUFSIZ]; struct passwd pw; struct passwd *ppw; gid_t root_gid; int ret; char *userLocal; ppw = &pw; if ((ppw = getpwuid_r(0, &pw, buffer, sizeof buffer)) == NULL) { return FALSE; } root_gid = ppw->pw_gid; /* convert user name to local character set */ userLocal = (char *)Unicode_GetAllocBytes(user, Unicode_GetCurrentEncoding()); if (!userLocal) { Warning("Failed to convert user name %s to local character set.\n", user); return FALSE; } ppw = getpwnam_r(userLocal, &pw, buffer, sizeof buffer); free(userLocal); if (ppw == NULL) { return FALSE; } /* first change group. */ ret = Id_SetGid(root_gid); if (ret < 0) { Warning("Failed to setregid() for root\n"); return FALSE; } /* Snippet from Solaris setregid man page -- * * A -1 argument does not change the corresponding gid. If the real user ID * is being changed, or the effective user ID is being changed to a value * not equal to the real user ID, the saved set-user ID is set equal to * the new effective user ID. */ ret = Id_SetREGid(ppw->pw_gid, -1); if (ret < 0) { Warning("Failed to setregid() for user %s\n", user); return FALSE; } ret = Id_SetREGid(-1, ppw->pw_gid); if (ret < 0) { Warning("Failed to setregid() for user %s\n", user); return FALSE; } ret = initgroups(ppw->pw_name, ppw->pw_gid); if (ret < 0) { Warning("Failed to initgroups() for user %s\n", user); goto failure; } /* now user. */ ret = Id_SetUid(0); if (ret < 0) { Warning("Failed to setregid() for root\n"); return FALSE; } /* Same as above. */ ret = Id_SetREUid(ppw->pw_uid, -1); if (ret < 0) { Warning("Failed to setreuid() for user %s\n", user); goto failure; } ret = Id_SetREUid(-1, ppw->pw_uid); if (ret < 0) { Warning("Failed to setreuid() for user %s\n", user); goto failure; } /* set env. */ setenv("USER", ppw->pw_name, 1); setenv("HOME", ppw->pw_dir, 1); setenv("SHELL", ppw->pw_shell, 1); return TRUE; failure: /* try to restore on error. */ ProcMgr_ImpersonateUserStop(); return FALSE; }