2010-05-26 3 views
42

Linux에서 실행되는 C++ 프로그램에서 사용자 홈 디렉토리를 얻는 방법이 필요합니다. 동일한 코드가 유닉스에서 작동한다면, 좋을 것이다. HOME 환경 값을 사용하고 싶지 않습니다.리눅스에서 홈 디렉토리 가져 오기 C++

AFAIK, 루트 홈 디렉토리는/root입니다. 내 프로그램이 루트 사용자에 의해 실행되는 경우이 디렉토리에 파일/폴더를 만드는 것이 좋습니까?

#include <unistd.h> 
#include <sys/types.h> 
#include <pwd.h> 

struct passwd *pw = getpwuid(getuid()); 

const char *homedir = pw->pw_dir; 

참고 :

+2

'~'그것입니다 아니? 'cd ~','mv some_file ~/some_file' 등. –

+14

@NickBedford -'~'는 커널이나 libc가 아닌 쉘에 의해 구현됩니다. C++로 프로그래밍 할 때는 직접 구현해야합니다. –

+1

@Samuel의 설명에 감사드립니다. –

답변

72
당신은 현재 사용자의 사용자 ID를 얻을 수 getuid 필요

다음 getpwuid 해당 사용자의 (홈 디렉토리 포함) 암호 입력을 얻기 위해 당신이이 필요한 경우 대신에 getpwuid_r을 사용하고 싶을 것입니다.

+38

'getpwuid()'맨 페이지에는 다음과 같은주의 사항이 있습니다 : * 사용자의 홈 디렉토리를 결정하고자하는 응용 프로그램은'getpwuid (getuid()) -> pw_dir이 아닌'HOME'의 값을 조사해야합니다. ') 이것은 사용자가 로그인 세션 중에 "홈 디렉토리"라는 개념을 수정할 수있게하기 때문에 * – caf

+16

getenv ("HOME")을 먼저 확인한 다음 getpwuid()를 호출합니다. –

+0

이것은 원래 질문에 대한 좋은 대답이 아닙니다 . 이것은'/ etc/passwd'에 설정된 쉘 시작 디렉토리이며 사용자의 (활성) 홈 디렉토리 일 수도 그렇지 않을 수도 있습니다. 이것은 유용한 정보이지만'getenv'가 올바른 대답입니다. –

1

루트로 프로그램을 실행하는 경우이 디렉토리에 대한 rwx 액세스 권한이 있습니다. 그 안에 물건을 만드는 것은 괜찮습니다.

+1

/root가 특정 시스템에서 root의 홈 디렉토리라는 보장은 없습니다.일반적으로 경로를 응용 프로그램에 하드 코딩하는 것은 매우 바람직하지 않습니다. 소프트웨어가 이식성이 떨어지기 때문입니다. HOMEDIR을 달리 결정할 수없는 경우/root를 기본값으로 사용하면 구성을 통해이를 덮어 쓰는 방법이있는 한 적당합니다. –

+0

@Hypher 질문에 대한 대답은 "내 프로그램이 루트 사용자에 의해 실행되는 경우이 디렉토리 [/ root]에 파일/폴더를 만들면 괜찮습니까?" "예"입니다. – Anthony

44

우선 환경 변수 $HOME을 확인하고, 이것이 존재하지 않으면 getpwuid를 사용하십시오.

#include <unistd.h> 
#include <sys/types.h> 
#include <pwd.h> 

const char *homedir; 

if ((homedir = getenv("HOME")) == NULL) { 
    homedir = getpwuid(getuid())->pw_dir; 
} 

은 또한 당신은 XDG Base Directory Specification 다음 고려해야합니다, 당신이 원하는 경우 홈 디렉토리는 당신이 쓰는 프로그램의 한 부분으로 구성 또는 캐시 데이터를 저장하고 사용자에게 배포 할 것을주의. 예를 들어 응용 프로그램의 구성 디렉토리를 만들려면 위의 그림과 같이 getenv을 사용하여 $XDG_CONFIG_HOME을 먼저 확인하고 변수가 설정되지 않은 경우 위의 코드로 되돌아 가야합니다.

당신이 멀티 스레드 안전을 필요로하는 경우이 같은 getpwuid_r 대신 getpwuid를 사용해야합니다 (getpwnam(3) 사람 페이지에서) :

사용자 (이름없는) 현재 홈 디렉토리가
struct passwd pwd; 
struct passwd *result; 
char *buf; 
size_t bufsize; 
int s; 
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); 
if (bufsize == -1) 
    bufsize = 16384; 
buf = malloc(bufsize); 
if (buf == NULL) { 
    perror("malloc"); 
    exit(EXIT_FAILURE); 
} 
s = getpwuid_r(getuid(), &pwd, buf, bufsize, &result); 
if (result == NULL) { 
    if (s == 0) 
     printf("Not found\n"); 
    else { 
     errno = s; 
     perror("getpwnam_r"); 
    } 
    exit(EXIT_FAILURE); 
} 
char *homedir = result.pw_dir; 
+0

거기에 뮤텍스가 필요할 수 있습니다. 그렇지 않으면 유일한 방법은'getpwuid_r'입니다. 왜 그 기능이 로케일과 어울리는 지, 나는 모른다. – user877329

+0

그건 buf가없는 것 같습니다. –

+1

@ChrisSherlock'getpwuid_r'의 man 페이지에 따르면,'free (buf)'를 내 대답에 넣으면 오해의 소지가있어 너무 이른'free()'문제가 생길 수 있습니다. passwd 구조체의 멤버가 가리키는 "buflen"버퍼 buf에 저장됩니다. " 그래서'buf'는'pwd'가 유용하다면 유용합니다. – josch

관련 문제