7
Sumit Bose <sbose@redhat.com>
9
Copyright (C) 2009 Red Hat
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 3 of the License, or
14
(at your option) any later version.
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program. If not, see <http://www.gnu.org/licenses/>.
26
#include <sys/types.h>
40
#include "util/util.h"
41
#include "util/strtonum.h"
43
#define INITIAL_TABLE_SIZE 64
44
#define PATHLEN (NAME_MAX + 14)
47
static void *hash_talloc(const size_t size, void *pvt)
49
return talloc_size(pvt, size);
52
static void hash_talloc_free(void *ptr, void *pvt)
57
static errno_t get_uid_from_pid(const pid_t pid, uid_t *uid)
70
ret = snprintf(path, PATHLEN, "/proc/%d/status", pid);
72
DEBUG(1, ("snprintf failed"));
74
} else if (ret >= PATHLEN) {
75
DEBUG(1, ("path too long?!?!\n"));
79
fd = open(path, O_RDONLY);
82
if (error == ENOENT) {
83
DEBUG(7, ("Proc file [%s] is not available anymore, continuing.\n",
87
DEBUG(1, ("open failed [%d][%s].\n", error, strerror(error)));
91
ret = fstat(fd, &stat_buf);
94
if (error == ENOENT) {
95
DEBUG(7, ("Proc file [%s] is not available anymore, continuing.\n",
99
DEBUG(1, ("fstat failed [%d][%s].\n", error, strerror(error)));
103
if (!S_ISREG(stat_buf.st_mode)) {
104
DEBUG(1, ("not a regular file\n"));
108
while ((ret = read(fd, buf, BUFSIZE)) != 0) {
111
if (error == EINTR || error == EAGAIN) {
114
DEBUG(1, ("read failed [%d][%s].\n", error, strerror(error)));
122
DEBUG(1, ("close failed [%d][%s].\n", error, strerror(error)));
125
p = strstr(buf, "\nUid:\t");
130
DEBUG(1, ("missing delimiter.\n"));
135
num = strtouint32(p, &endptr, 10);
138
DEBUG(1, ("strtol failed [%s].\n", strerror(error)));
141
if (*endptr != '\0') {
142
DEBUG(1, ("uid contains extra characters\n"));
146
if (num >= UINT32_MAX) {
147
DEBUG(1, ("uid out of range.\n"));
152
DEBUG(1, ("format error\n"));
161
static errno_t name_to_pid(const char *name, pid_t *pid)
168
num = strtol(name, &endptr, 10);
170
if (error == ERANGE) {
175
if (*endptr != '\0') {
176
DEBUG(1, ("pid string contains extra characters.\n"));
180
if (num <= 0 || num >= INT_MAX) {
181
DEBUG(1, ("pid out of range.\n"));
190
static int only_numbers(char *p)
192
while(*p!='\0' && isdigit(*p)) ++p;
196
static errno_t get_active_uid_linux(hash_table_t *table, uid_t search_uid)
198
DIR *proc_dir = NULL;
199
struct dirent *dirent;
207
proc_dir = opendir("/proc");
208
if (proc_dir == NULL) {
210
DEBUG(1, ("Cannot open proc dir.\n"));
215
while ((dirent = readdir(proc_dir)) != NULL) {
216
if (only_numbers(dirent->d_name) != 0) continue;
217
ret = name_to_pid(dirent->d_name, &pid);
219
DEBUG(1, ("name_to_pid failed.\n"));
223
ret = get_uid_from_pid(pid, &uid);
225
DEBUG(1, ("get_uid_from_pid failed.\n"));
230
key.type = HASH_KEY_ULONG;
231
key.ul = (unsigned long) uid;
232
value.type = HASH_VALUE_ULONG;
233
value.ul = (unsigned long) uid;
235
ret = hash_enter(table, &key, &value);
236
if (ret != HASH_SUCCESS) {
237
DEBUG(1, ("cannot add to table [%s]\n", hash_error_string(ret)));
242
if (uid == search_uid) {
251
if (errno != 0 && dirent == NULL) {
253
DEBUG(1, ("readdir failed.\n"));
257
ret = closedir(proc_dir);
260
DEBUG(1, ("closedir failed, watch out.\n"));
270
if (proc_dir != NULL) {
271
err = closedir(proc_dir);
273
DEBUG(1, ("closedir failed, bad dirp?\n"));
279
errno_t get_uid_table(TALLOC_CTX *mem_ctx, hash_table_t **table)
284
ret = hash_create_ex(INITIAL_TABLE_SIZE, table, 0, 0, 0, 0,
285
hash_talloc, hash_talloc_free, mem_ctx,
287
if (ret != HASH_SUCCESS) {
288
DEBUG(1, ("hash_create_ex failed [%s]\n", hash_error_string(ret)));
292
return get_active_uid_linux(*table, 0);
298
errno_t check_if_uid_is_active(uid_t uid, bool *result)
302
ret = get_active_uid_linux(NULL, uid);
303
if (ret != EOK && ret != ENOENT) {
304
DEBUG(1, ("get_uid_table failed.\n"));