headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / libroot / posix / pwd.cpp
blob7d844519630ce2f6255c06ead1af0f0979d7c353
1 /*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <pwd.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <unistd.h>
12 #include <new>
14 #include <OS.h>
16 #include <errno_private.h>
17 #include <libroot_private.h>
18 #include <RegistrarDefs.h>
19 #include <user_group.h>
21 #include <util/KMessage.h>
24 using BPrivate::UserGroupLocker;
25 using BPrivate::relocate_pointer;
28 static KMessage sPasswdDBReply;
29 static passwd** sPasswdEntries = NULL;
30 static size_t sPasswdEntryCount = 0;
31 static size_t sIterationIndex = 0;
33 static struct passwd sPasswdBuffer;
34 static char sPasswdStringBuffer[MAX_PASSWD_BUFFER_SIZE];
37 static status_t
38 query_passwd_entry(const char* name, uid_t _uid, struct passwd *passwd,
39 char *buffer, size_t bufferSize, struct passwd **_result)
41 *_result = NULL;
43 KMessage message(BPrivate::B_REG_GET_USER);
44 if (name)
45 message.AddString("name", name);
46 else
47 message.AddInt32("uid", _uid);
49 KMessage reply;
50 status_t error = BPrivate::send_authentication_request_to_registrar(message,
51 reply);
52 if (error != B_OK)
53 return error == ENOENT ? B_OK : error;
55 int32 uid;
56 int32 gid;
57 const char* password;
58 const char* home;
59 const char* shell;
60 const char* realName;
62 if ((error = reply.FindInt32("uid", &uid)) != B_OK
63 || (error = reply.FindInt32("gid", &gid)) != B_OK
64 || (error = reply.FindString("name", &name)) != B_OK
65 || (error = reply.FindString("password", &password)) != B_OK
66 || (error = reply.FindString("home", &home)) != B_OK
67 || (error = reply.FindString("shell", &shell)) != B_OK
68 || (error = reply.FindString("real name", &realName)) != B_OK) {
69 return error;
72 error = BPrivate::copy_passwd_to_buffer(name, password, uid, gid, home,
73 shell, realName, passwd, buffer, bufferSize);
74 if (error == B_OK)
75 *_result = passwd;
77 return error;
81 static status_t
82 init_passwd_db()
84 if (sPasswdEntries != NULL)
85 return B_OK;
87 // ask the registrar
88 KMessage message(BPrivate::B_REG_GET_PASSWD_DB);
89 status_t error = BPrivate::send_authentication_request_to_registrar(message,
90 sPasswdDBReply);
91 if (error != B_OK)
92 return error;
94 // unpack the reply
95 int32 count;
96 passwd** entries;
97 int32 numBytes;
98 if ((error = sPasswdDBReply.FindInt32("count", &count)) != B_OK
99 || (error = sPasswdDBReply.FindData("entries", B_RAW_TYPE,
100 (const void**)&entries, &numBytes)) != B_OK) {
101 return error;
104 // relocate the entries
105 addr_t baseAddress = (addr_t)entries;
106 for (int32 i = 0; i < count; i++) {
107 passwd* entry = relocate_pointer(baseAddress, entries[i]);
108 relocate_pointer(baseAddress, entry->pw_name);
109 relocate_pointer(baseAddress, entry->pw_passwd);
110 relocate_pointer(baseAddress, entry->pw_dir);
111 relocate_pointer(baseAddress, entry->pw_shell);
112 relocate_pointer(baseAddress, entry->pw_gecos);
115 sPasswdEntries = entries;
116 sPasswdEntryCount = count;
118 return B_OK;
122 // #pragma mark -
125 struct passwd*
126 getpwent(void)
128 struct passwd* result = NULL;
129 int status = getpwent_r(&sPasswdBuffer, sPasswdStringBuffer,
130 sizeof(sPasswdStringBuffer), &result);
131 if (status != 0)
132 __set_errno(status);
133 return result;
138 getpwent_r(struct passwd* passwd, char* buffer, size_t bufferSize,
139 struct passwd** _result)
141 UserGroupLocker _;
143 int status = B_NO_MEMORY;
145 *_result = NULL;
147 if ((status = init_passwd_db()) == B_OK) {
148 if (sIterationIndex >= sPasswdEntryCount)
149 return ENOENT;
151 status = BPrivate::copy_passwd_to_buffer(
152 sPasswdEntries[sIterationIndex], passwd, buffer, bufferSize);
154 if (status == B_OK) {
155 sIterationIndex++;
156 *_result = passwd;
160 return status;
164 void
165 setpwent(void)
167 UserGroupLocker _;
169 sIterationIndex = 0;
173 void
174 endpwent(void)
176 UserGroupLocker locker;
178 sPasswdDBReply.Unset();
179 sPasswdEntries = NULL;
180 sPasswdEntryCount = 0;
181 sIterationIndex = 0;
185 struct passwd *
186 getpwnam(const char *name)
188 struct passwd* result = NULL;
189 int status = getpwnam_r(name, &sPasswdBuffer, sPasswdStringBuffer,
190 sizeof(sPasswdStringBuffer), &result);
191 if (status != 0)
192 __set_errno(status);
193 return result;
198 getpwnam_r(const char *name, struct passwd *passwd, char *buffer,
199 size_t bufferSize, struct passwd **_result)
201 return query_passwd_entry(name, 0, passwd, buffer, bufferSize, _result);
205 struct passwd *
206 getpwuid(uid_t uid)
208 struct passwd* result = NULL;
209 int status = getpwuid_r(uid, &sPasswdBuffer, sPasswdStringBuffer,
210 sizeof(sPasswdStringBuffer), &result);
211 if (status != 0)
212 __set_errno(status);
213 return result;
218 getpwuid_r(uid_t uid, struct passwd *passwd, char *buffer,
219 size_t bufferSize, struct passwd **_result)
221 return query_passwd_entry(NULL, uid, passwd, buffer, bufferSize, _result);