1// This is an open source non-commercial project. Dear PVS-Studio, please check
2// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3
4// users.c -- operating system user information
5
6#include <uv.h>
7
8#include "nvim/ascii.h"
9#include "nvim/os/os.h"
10#include "nvim/garray.h"
11#include "nvim/memory.h"
12#include "nvim/strings.h"
13#ifdef HAVE_PWD_H
14# include <pwd.h>
15#endif
16
17// Initialize users garray and fill it with os usernames.
18// Return Ok for success, FAIL for failure.
19int os_get_usernames(garray_T *users)
20{
21 if (users == NULL) {
22 return FAIL;
23 }
24 ga_init(users, sizeof(char *), 20);
25
26# if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H)
27 struct passwd *pw;
28
29 setpwent();
30 while ((pw = getpwent()) != NULL) {
31 // pw->pw_name shouldn't be NULL but just in case...
32 if (pw->pw_name != NULL) {
33 GA_APPEND(char *, users, xstrdup(pw->pw_name));
34 }
35 }
36 endpwent();
37# endif
38
39 return OK;
40}
41
42// Insert user name in s[len].
43// Return OK if a name found.
44int os_get_user_name(char *s, size_t len)
45{
46#ifdef UNIX
47 return os_get_uname((uv_uid_t)getuid(), s, len);
48#else
49 // TODO(equalsraf): Windows GetUserName()
50 return os_get_uname((uv_uid_t)0, s, len);
51#endif
52}
53
54// Insert user name for "uid" in s[len].
55// Return OK if a name found.
56// If the name is not found, write the uid into s[len] and return FAIL.
57int os_get_uname(uv_uid_t uid, char *s, size_t len)
58{
59#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
60 struct passwd *pw;
61
62 if ((pw = getpwuid(uid)) != NULL // NOLINT(runtime/threadsafe_fn)
63 && pw->pw_name != NULL && *(pw->pw_name) != NUL) {
64 STRLCPY(s, pw->pw_name, len);
65 return OK;
66 }
67#endif
68 snprintf(s, len, "%d", (int)uid);
69 return FAIL; // a number is not a name
70}
71
72// Returns the user directory for the given username.
73// The caller has to free() the returned string.
74// If the username is not found, NULL is returned.
75char *os_get_user_directory(const char *name)
76{
77#if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
78 if (name == NULL || *name == NUL) {
79 return NULL;
80 }
81 struct passwd *pw = getpwnam(name); // NOLINT(runtime/threadsafe_fn)
82 if (pw != NULL) {
83 // save the string from the static passwd entry into malloced memory
84 return xstrdup(pw->pw_dir);
85 }
86#endif
87 return NULL;
88}
89
90