toaruos/libc/pwd/pwd.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;
}