diff --git a/Userspace/libc/include/pwd.h b/Userspace/libc/include/pwd.h index 79d67523..07d2df90 100644 --- a/Userspace/libc/include/pwd.h +++ b/Userspace/libc/include/pwd.h @@ -25,21 +25,43 @@ extern "C" #include + /** + * /etc/passwd + * name:passwd:uid:gid:gecos:dir:shell + * + * Example + * + * root:x:0:0:root:/root:/bin/sh + * | | | | | | | + * | | | | | | \-- pw_shell + * | | | | | \-- pw_dir + * | | | | \-- pw_gecos + * | | | \-- pw_gid + * | | \-- pw_uid + * | \-- pw_passwd + * \-- pw_name + * + * @ref https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/pwd.h.html + * @ref https://man7.org/linux/man-pages/man3/getpw.3.html + * @ref https://man7.org/linux/man-pages/man5/passwd.5.html + */ struct passwd { - char *pw_name; /* User's login name. */ - uid_t pw_uid; /* Numerical user ID. */ - gid_t pw_gid; /* Numerical group ID. */ - char *pw_dir; /* Initial working directory. */ - char *pw_shell; /* Program to use as shell. */ + char *pw_name; /* User's login name. */ + char *pw_passwd; /* User password. */ + uid_t pw_uid; /* Numerical user ID. */ + gid_t pw_gid; /* Numerical group ID. */ + char *pw_gecos; /* User information. */ + char *pw_dir; /* Initial working directory. */ + char *pw_shell; /* Program to use as shell. */ }; void endpwent(void); struct passwd *getpwent(void); - struct passwd *getpwnam(const char *); - int getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **); - struct passwd *getpwuid(uid_t); - int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **); + struct passwd *getpwnam(const char *name); + int getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result); + struct passwd *getpwuid(uid_t uid); + int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result); void setpwent(void); #ifdef __cplusplus diff --git a/Userspace/libc/src/std/pwd.c b/Userspace/libc/src/std/pwd.c new file mode 100644 index 00000000..d92caa01 --- /dev/null +++ b/Userspace/libc/src/std/pwd.c @@ -0,0 +1,151 @@ +/* + This file is part of Fennix C Library. + + Fennix C Library is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix C Library. If not, see . +*/ + +#include +#include +#include +#include + +export void endpwent(void) +{ + /* FIXME */ +} + +export struct passwd *getpwent(void) +{ + static FILE *pwfile = NULL; + static struct passwd pwd; + static char line[256]; + + if (pwfile == NULL) + { + pwfile = fopen("/etc/passwd", "r"); + if (pwfile == NULL) + return NULL; + } + + if (fgets(line, sizeof(line), pwfile) == NULL) + { + fclose(pwfile); + pwfile = NULL; + return NULL; + } + + char *token = strtok(line, ":"); + pwd.pw_name = token; + + token = strtok(NULL, ":"); + pwd.pw_passwd = token; + + token = strtok(NULL, ":"); + pwd.pw_uid = atoi(token); + + token = strtok(NULL, ":"); + pwd.pw_gid = atoi(token); + + token = strtok(NULL, ":"); + pwd.pw_gecos = token; + + token = strtok(NULL, ":"); + pwd.pw_dir = token; + + token = strtok(NULL, ":"); + pwd.pw_shell = token; + + return &pwd; +} + +export struct passwd *getpwnam(const char *name) +{ + struct passwd *pwd; + setpwent(); + while ((pwd = getpwent()) != NULL) + { + if (strcmp(pwd->pw_name, name) == 0) + { + endpwent(); + return pwd; + } + } + endpwent(); + return NULL; +} + +export int getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) +{ + FILE *pwfile; + char line[256]; + struct passwd *pwd_entry; + + setpwent(); + while ((pwd_entry = getpwent()) != NULL) + { + if (strcmp(pwd_entry->pw_name, name) == 0) + { + *pwd = *pwd_entry; + *result = pwd; + endpwent(); + return 0; + } + } + endpwent(); + *result = NULL; + return 0; +} + +export struct passwd *getpwuid(uid_t uid) +{ + struct passwd *pwd; + setpwent(); + while ((pwd = getpwent()) != NULL) + { + if (pwd->pw_uid == uid) + { + endpwent(); + return pwd; + } + } + endpwent(); + return NULL; +} + +export int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) +{ + FILE *pwfile; + char line[256]; + struct passwd *pwd_entry; + + setpwent(); + while ((pwd_entry = getpwent()) != NULL) + { + if (pwd_entry->pw_uid == uid) + { + *pwd = *pwd_entry; + *result = pwd; + endpwent(); + return 0; + } + } + endpwent(); + *result = NULL; + return 0; +} + +export void setpwent(void) +{ + /* FIXME */ +}