The R Project SVN R

Rev

Rev 83598 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 83598 Rev 83755
Line 1... Line 1...
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  file shext.c
3
 *  file shext.c
4
 *  Copyright (C) 2001  Guido Masarotto and Brian Ripley
4
 *  Copyright (C) 2001  Guido Masarotto and Brian Ripley
5
 *                2004-2022  R Core Team
5
 *                2004-2023  R Core Team
6
 *
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
10
 *  (at your option) any later version.
Line 20... Line 20...
20
 */
20
 */
21
 
21
 
22
#define WIN32_LEAN_AND_MEAN 1
22
#define WIN32_LEAN_AND_MEAN 1
23
#include <windows.h>
23
#include <windows.h>
24
#include <shlobj.h>
24
#include <shlobj.h>
-
 
25
#include <knownfolders.h>
-
 
26
#include <stdlib.h>
25
 
27
 
26
static int ShellGetPersonalDirectory(char *folder)
28
static char *ShellGetPersonalDirectory(void)
27
  /* Folder is assumed to be at least MAX_PATH long */
-
 
28
{
29
{
29
    LPMALLOC g_pMalloc;
30
    wchar_t *wpath;
30
    LPITEMIDLIST pidlUser;
-
 
31
    int result;
31
    char *result = NULL;
32
 
32
 
33
    result = 0;
33
    /* CSIDL_PERSONAL */
34
 
-
 
35
    /* Get the shell's allocator. */
34
    if (SHGetKnownFolderPath(&FOLDERID_Documents, KF_FLAG_CREATE, NULL,
36
    if (SUCCEEDED(SHGetMalloc(&g_pMalloc))) {
35
                             &wpath) == S_OK) {
37
 
-
 
38
	/* Get the PIDL of the user's Directory. */
36
	size_t needed = wcstombs(NULL, wpath, 0);
-
 
37
	if (needed != (size_t)-1) {
39
	if (SUCCEEDED(SHGetSpecialFolderLocation(0, CSIDL_PERSONAL, &pidlUser))) {
38
	    result = (char *)malloc(needed + 1);
-
 
39
	    if (result)
40
	    if (SUCCEEDED(SHGetPathFromIDList(pidlUser, folder))) result = 1;
40
		/* NOTE: some characters may not be representable */
41
	    g_pMalloc->lpVtbl->Free(g_pMalloc, pidlUser);
41
		wcstombs(result, wpath, needed + 1);
42
	}
42
	}
43
    }
43
    }
-
 
44
    CoTaskMemFree(wpath);
44
    return(result);
45
    return result;
45
}
46
}
46
 
47
 
47
 
-
 
48
static char RUser[MAX_PATH];
-
 
49
#include <winbase.h>
48
#include <winbase.h>
50
extern void R_Suicide(char *s);
49
extern void R_Suicide(char *s);
51
 
50
 
-
 
51
/* Returns a result to be freed by freeRUser(). Previously, pointer to a static
-
 
52
   fixed-size buffer has been returned, so older embedding applications would
-
 
53
   not know to free the result, but they would probably call this function only
-
 
54
   once. */
52
char *getRUser()
55
char *getRUser(void)
53
{
56
{
54
    /*
57
    /*
55
     * try R_USER then HOME then Windows homes then working directory
58
     * try R_USER then HOME then Windows homes then working directory
56
     */
59
     */
57
    char *p, *q;
60
    char *p, *q;
-
 
61
    char *RUser = NULL;
58
 
62
 
59
    if ((p = getenv("R_USER"))) {
63
    if ((p = getenv("R_USER")) || (p = getenv("HOME"))) {
60
	if(strlen(p) >= MAX_PATH) R_Suicide("Invalid R_USER");
64
	RUser = (char *)malloc(strlen(p) + 1);
61
	strcpy(RUser, p);
65
	if (RUser)
62
    } else if ((p = getenv("HOME"))) {
-
 
63
	if(strlen(p) >= MAX_PATH) R_Suicide("Invalid HOME");
-
 
64
	strcpy(RUser, p);
66
	    strcpy(RUser, p);
65
    } else if (ShellGetPersonalDirectory(RUser)) {
67
    } else if ((RUser = ShellGetPersonalDirectory())) {
66
	/* nothing to do */;
68
	/* nothing to do */;
67
    } else if ((p = getenv("HOMEDRIVE")) && (q = getenv("HOMEPATH"))) {
69
    } else if ((p = getenv("HOMEDRIVE")) && (q = getenv("HOMEPATH"))) {
68
	if(strlen(p) >= MAX_PATH) R_Suicide("Invalid HOMEDRIVE");
70
	RUser = (char *)malloc(strlen(p) + strlen(q) + 1);
69
	strcpy(RUser, p);
71
	strcpy(RUser, p);
70
	if(strlen(RUser) + strlen(q) >= MAX_PATH)
-
 
71
	    R_Suicide("Invalid HOMEDRIVE+HOMEPATH");
-
 
72
	strcat(RUser, q);
72
	strcat(RUser, q);
73
    } else {
73
    } else {
-
 
74
	DWORD res = GetCurrentDirectory(0, NULL);
-
 
75
	if (res) {
-
 
76
	    RUser = (char *)malloc(res);
74
	GetCurrentDirectory(MAX_PATH, RUser);
77
	    if (!GetCurrentDirectory(res, RUser)) {
-
 
78
		free(RUser);
-
 
79
		RUser = NULL;
-
 
80
	    }
-
 
81
	}
75
    }
82
    }
-
 
83
    if (!RUser)
-
 
84
	R_Suicide("Cannot determine R user directory");
-
 
85
 
76
    p = RUser + (strlen(RUser) - 1);
86
    p = RUser + (strlen(RUser) - 1);
77
    /* remove trailing file separator(s), unless root directory on a drive */
87
    /* remove trailing file separator(s), unless root directory on a drive */
78
    while (p > RUser && (*p == '/' || *p == '\\')
88
    while (p > RUser && (*p == '/' || *p == '\\')
79
           && (p > RUser+2 || *(p-1) != ':'))  *p-- = '\0';
89
           && (p > RUser+2 || *(p-1) != ':'))  *p-- = '\0';
80
    return RUser;
90
    return RUser;
81
}
91
}
-
 
92
 
-
 
93
void freeRUser(char *s)
-
 
94
{
-
 
95
    free(s);
-
 
96
}
-
 
97