141 lines
2.5 KiB
C
141 lines
2.5 KiB
C
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
|
* This file is part of ToaruOS and is released under the terms
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
* Copyright (C) 2013-2018 K. Lange
|
|
*
|
|
* getpwent, setpwent, endpwent, fgetpwent
|
|
* getpwuid, getpwnam
|
|
*
|
|
* These functions manage entries in the password files.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <pwd.h>
|
|
|
|
/*
|
|
struct passwd {
|
|
char * pw_name; // username
|
|
char * pw_passwd; // password (not meaningful)
|
|
uid_t pw_uid; // user id
|
|
gid_t pw_gid; // group id
|
|
char * pw_comment; // used for decoration settings in toaruos
|
|
char * pw_gecos; // full name
|
|
char * pw_dir; // home directory
|
|
char * pw_shell; // shell
|
|
}
|
|
*/
|
|
|
|
static FILE * pwdb = NULL;
|
|
|
|
static void open_it(void) {
|
|
pwdb = fopen("/etc/passwd", "r");
|
|
}
|
|
|
|
#define LINE_LEN 2048
|
|
|
|
static struct passwd * pw_ent;
|
|
static char * pw_blob;
|
|
|
|
struct passwd * fgetpwent(FILE * stream) {
|
|
if (!stream) {
|
|
return NULL;
|
|
}
|
|
if (!pw_ent) {
|
|
pw_ent = malloc(sizeof(struct passwd));
|
|
pw_blob = malloc(LINE_LEN);
|
|
}
|
|
|
|
memset(pw_blob, 0x00, LINE_LEN);
|
|
fgets(pw_blob, LINE_LEN, stream);
|
|
|
|
|
|
if (pw_blob[strlen(pw_blob)-1] == '\n') {
|
|
pw_blob[strlen(pw_blob)-1] = '\0'; /* erase newline */
|
|
}
|
|
|
|
/* Tokenize */
|
|
char *p, *tokens[8], *last;
|
|
int i = 0;
|
|
for ((p = strtok_r(pw_blob, ":", &last)); p;
|
|
(p = strtok_r(NULL, ":", &last)), i++) {
|
|
tokens[i] = p;
|
|
}
|
|
|
|
if (i < 8) return NULL;
|
|
|
|
pw_ent->pw_name = tokens[0];
|
|
pw_ent->pw_passwd = tokens[1];
|
|
pw_ent->pw_uid = atoi(tokens[2]);
|
|
pw_ent->pw_gid = atoi(tokens[3]);
|
|
pw_ent->pw_gecos = tokens[4];
|
|
pw_ent->pw_dir = tokens[5];
|
|
pw_ent->pw_shell = tokens[6];
|
|
pw_ent->pw_comment = tokens[7];
|
|
|
|
return pw_ent;
|
|
}
|
|
|
|
struct passwd * getpwent(void) {
|
|
if (!pwdb) {
|
|
open_it();
|
|
}
|
|
|
|
if (!pwdb) {
|
|
return NULL;
|
|
}
|
|
|
|
return fgetpwent(pwdb);
|
|
}
|
|
|
|
void setpwent(void) {
|
|
/* Reset stream to beginning */
|
|
if (pwdb) rewind(pwdb);
|
|
}
|
|
|
|
void endpwent(void) {
|
|
/* Close stream */
|
|
if (pwdb) {
|
|
fclose(pwdb);
|
|
pwdb = NULL;
|
|
}
|
|
if (pw_ent) {
|
|
free(pw_ent);
|
|
free(pw_blob);
|
|
pw_ent = NULL;
|
|
pw_blob = NULL;
|
|
}
|
|
}
|
|
|
|
struct passwd * getpwnam(const char * name) {
|
|
struct passwd * p;
|
|
|
|
setpwent();
|
|
|
|
while ((p = getpwent())) {
|
|
if (!strcmp(p->pw_name, name)) {
|
|
return p;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct passwd * getpwuid(uid_t uid) {
|
|
struct passwd * p;
|
|
|
|
setpwent();
|
|
|
|
while ((p = getpwent())) {
|
|
if (p->pw_uid == uid) {
|
|
return p;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|