512
*-----------------------------------------------------------------------------
514
* UtilIsAlphaOrNum --
516
* Checks if character is a numeric digit or a letter of the
520
* Returns TRUE if character is a digit or a letter, FALSE otherwise.
525
*-----------------------------------------------------------------------------
529
UtilIsAlphaOrNum(char ch) //IN
531
if ((ch >= '0' && ch <= '9') ||
532
(ch >= 'a' && ch <= 'z') ||
533
(ch >= 'A' && ch <= 'Z')) {
544
*-----------------------------------------------------------------------------
546
* UtilGetHomeDirectory --
548
* Unicode wrapper for posix getpwnam call for working directory.
551
* Returns initial working directory or NULL if it fails.
556
*-----------------------------------------------------------------------------
560
UtilGetHomeDirectory(const char *name) // IN: user name
567
pwd = Posix_Getpwnam(name);
568
if (pwd && pwd->pw_dir) {
569
dir = Util_SafeStrdup(pwd->pw_dir);
580
*-----------------------------------------------------------------------------
582
* UtilGetLoginName --
584
* Unicode wrapper for posix getpwnam call for working directory.
587
* Returns user's login name or NULL if it fails.
592
*-----------------------------------------------------------------------------
596
UtilGetLoginName(int uid) //IN: user id
601
pwd = Posix_Getpwuid(uid);
602
if (pwd && pwd->pw_name) {
603
name = Util_SafeStrdup(pwd->pw_name);
614
*----------------------------------------------------------------------
616
* UtilDoTildeSubst --
618
* Given a string following a tilde, this routine returns the
619
* corresponding home directory.
622
* The result is a pointer to a static string containing the home
623
* directory in native format. The returned string is a newly
624
* allocated string which may/must be freed by the caller
627
* Information may be left in resultPtr.
629
* Credit: derived from J.K.Ousterhout's Tcl
630
*----------------------------------------------------------------------
634
UtilDoTildeSubst(Unicode user) // IN - name of user
639
str = Unicode_Duplicate(Posix_Getenv("HOME"));
641
Log("Could not expand environment variable HOME.\n");
644
str = UtilGetHomeDirectory(user);
646
Log("Could not get information for user '%s'.\n", user);
656
*----------------------------------------------------------------------
658
* Util_ExpandString --
660
* converts the strings by expanding "~", "~user" and environment
665
* Return a newly allocated string. The caller is responsible
666
* for deallocating it.
668
* Return NULL in case of error.
674
* the handling of enviroment variable references is very
675
* simplistic: there can be only one in a pathname segment
676
* and it must appear last in the string
678
*----------------------------------------------------------------------
681
#define UTIL_MAX_PATH_CHUNKS 100
684
Util_ExpandString(ConstUnicode fileName) // IN file path to expand
687
Unicode result = NULL;
689
char *chunks[UTIL_MAX_PATH_CHUNKS];
690
int chunkSize[UTIL_MAX_PATH_CHUNKS];
691
Bool freeChunk[UTIL_MAX_PATH_CHUNKS];
697
copy = Unicode_Duplicate(fileName);
702
if (!Unicode_StartsWith(fileName, "~") &&
703
Unicode_Find(fileName, "$") == UNICODE_INDEX_NOT_FOUND) {
708
* XXX Because the rest part of code depends pretty heavily from
709
* character pointer operations we want to leave it as-is and
710
* don't want to re-work it with using unicode library. However
711
* it's acceptable only until our Unicode type is utf-8 and
712
* until code below works correctly with utf-8.
716
* Break string into nice chunks for separate expansion.
718
* The rule for terminating a ~ expansion is historical. -- edward
722
for (cp = copy; *cp;) {
726
for (p = cp + 1; UtilIsAlphaOrNum(*p) || *p == '_'; p++) {
730
} else if (cp == copy && *cp == '~') {
731
len = strcspn(cp, DIRSEPS);
734
len = strcspn(cp, "$");
736
if (nchunk >= UTIL_MAX_PATH_CHUNKS) {
737
Log("%s: Filename \"%s\" has too many chunks.\n", __FUNCTION__,
742
chunkSize[nchunk] = len;
743
freeChunk[nchunk] = FALSE;
753
if (chunks[0][0] == '~') {
754
char save = (cp = chunks[0])[chunkSize[0]];
755
cp[chunkSize[0]] = 0;
756
ASSERT(!freeChunk[0]);
757
chunks[0] = UtilDoTildeSubst(chunks[0] + 1);
758
cp[chunkSize[0]] = save;
759
if (chunks[0] == NULL) {
760
/* It could not be expanded, therefore leave as original. */
763
/* It was expanded, so adjust the chunks. */
764
chunkSize[0] = strlen(chunks[0]);
774
for (i = 0; i < nchunk; i++) {
776
Unicode expand = NULL;
783
if (*cp != '$' || chunkSize[i] == 1) {
786
* Skip if the chuck has only the $ character.
787
* $ will be kept as a part of the pathname.
793
save = cp[chunkSize[i]];
794
cp[chunkSize[i]] = 0;
797
* $PID and $USER are interpreted specially.
798
* Others are just getenv().
801
expand = Unicode_Duplicate(Posix_Getenv(cp + 1));
802
if (expand != NULL) {
803
} else if (strcasecmp(cp + 1, "PID") == 0) {
804
Str_Snprintf(buf, sizeof buf, "%"FMTPID, getpid());
805
expand = Util_SafeStrdup(buf);
806
} else if (strcasecmp(cp + 1, "USER") == 0) {
809
expand = UtilGetLoginName(uid);
811
DWORD n = ARRAYSIZE(bufW);
812
if (GetUserNameW(bufW, &n)) {
813
expand = Unicode_AllocWithUTF16(bufW);
816
if (expand == NULL) {
817
expand = Unicode_Duplicate("unknown");
820
Warning("Environment variable '%s' not defined in '%s'.\n",
824
* Strip off the env variable string from the pathname.
827
expand = Unicode_Duplicate("");
832
* The problem is we have really no way to distinguish the caller's
833
* intention is a dollar sign ($) is used as a part of the pathname
834
* or as an environment variable.
836
* If the token does not expand to an environment variable,
837
* then assume it is a part of the pathname. Do not strip it
838
* off like it is done in linux host (see above)
840
* XXX We should also consider using %variable% convention instead
841
* of $variable for Windows platform.
844
Str_Strcpy(buf, cp, 100);
845
expand = Unicode_AllocWithUTF8(buf);
849
cp[chunkSize[i]] = save;
851
ASSERT(expand != NULL);
852
ASSERT(!freeChunk[i]);
854
if (chunks[i] == NULL) {
855
Log("%s: Cannot allocate memory to expand \"%s\" in \"%s\".\n",
856
__FUNCTION__, expand, UTF8(fileName));
859
chunkSize[i] = strlen(expand);
864
* Put all the chunks back together.
868
int size = 1; // 1 for the terminating null
869
for (i = 0; i < nchunk; i++) {
870
size += chunkSize[i];
872
result = malloc(size);
874
if (result == NULL) {
875
Log("%s: Cannot allocate memory for the expansion of \"%s\".\n",
876
__FUNCTION__, UTF8(fileName));
880
for (i = 0; i < nchunk; i++) {
881
memcpy(cp, chunks[i], chunkSize[i]);
888
* Clean up and return.
891
for (i = 0; i < nchunk; i++) {
509
901
#endif // N_PLAT_NLM