#define _GNU_SOURCE #include #include #include #include #include #include #include int strlcpy(char *restrict dest, const char *restrict src, size_t bufsize) { size_t i; for (i = 0; i < bufsize; ++i) { dest[i] = src[i]; if (src[i] == '\0') { return 0; } } return ERANGE; } char *getlogin(void) { return getenv("USER"); } int getlogin_r(char *buf, size_t bufsize) { const char *login = getlogin(); if (login == NULL) { return ENOENT; } return strlcpy(buf, login, bufsize); } struct passwd *getpwuid(uid_t uid) { struct passwd *(*getpwuid)(uid_t) = dlsym(RTLD_NEXT, "getpwuid"); if (getpwuid == NULL) { fprintf(stderr, "Unable to find the adress of the getpwuid function: %s\n", dlerror()); return NULL; } struct passwd *pass = getpwuid(uid); if (pass == NULL) { return NULL; } char *name = getenv("USER"); if (name == NULL) { fprintf(stderr, "Could not find the USER environment variable. Using the real username.\n"); return pass; } pass->pw_name = name; return pass; } int getpwuid_r(uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res) { int prev_err = errno; *res = NULL; struct passwd *pass = getpwuid(uid); if (pass == NULL || errno != prev_err) { return errno; } memcpy(pw, pass, sizeof(struct passwd)); size_t name_len = strlen(pass->pw_name) + 1; size_t passwd_len = strlen(pass->pw_passwd) + 1; size_t gecos_len = strlen(pass->pw_gecos) + 1; size_t dir_len = strlen(pass->pw_dir) + 1; size_t shell_len = strlen(pass->pw_shell) + 1; if ((name_len + passwd_len + gecos_len + dir_len + shell_len) > size) { return ERANGE; } pw->pw_name = memcpy(buf, pass->pw_name, name_len); pw->pw_passwd = memcpy(buf + name_len, pass->pw_passwd, passwd_len); pw->pw_gecos = memcpy(buf + name_len + passwd_len, pass->pw_gecos, gecos_len); pw->pw_dir = memcpy(buf + name_len + passwd_len + gecos_len, pass->pw_dir, dir_len); pw->pw_shell = memcpy(buf + name_len + passwd_len + gecos_len + dir_len, pass->pw_shell, shell_len); *res = pw; return 0; }