diff --git a/include/pwd.h b/include/pwd.h index aff3613749..205bd2f209 100644 --- a/include/pwd.h +++ b/include/pwd.h @@ -67,6 +67,12 @@ extern "C" #define EXTERN extern #endif +void setpwent(void); +void endpwent(void); +FAR struct passwd *getpwent(void); +int getpwent_r(FAR struct passwd *pwd, + FAR char *buf, size_t buflen, + FAR struct passwd **result); FAR struct passwd *getpwnam(FAR const char *name); FAR struct passwd *getpwuid(uid_t uid); int getpwnam_r(FAR const char *name, FAR struct passwd *pwd, FAR char *buf, diff --git a/libs/libc/pwd/Make.defs b/libs/libc/pwd/Make.defs index 73b7cb5130..6d6333ebb9 100644 --- a/libs/libc/pwd/Make.defs +++ b/libs/libc/pwd/Make.defs @@ -21,10 +21,10 @@ # Add the pwd C files to the build CSRCS += lib_getpwnam.c lib_getpwnamr.c lib_getpwuid.c lib_getpwuidr.c -CSRCS += lib_pwd_globals.c +CSRCS += lib_getpwent.c lib_pwd_globals.c ifeq ($(CONFIG_LIBC_PASSWD_FILE),y) -CSRCS += lib_find_pwdfile.c lib_pwd_globals.c +CSRCS += lib_find_pwdfile.c else CSRCS += lib_getpwbuf.c lib_getpwbufr.c endif diff --git a/libs/libc/pwd/lib_find_pwdfile.c b/libs/libc/pwd/lib_find_pwdfile.c index a7781631be..5cfa14da9d 100644 --- a/libs/libc/pwd/lib_find_pwdfile.c +++ b/libs/libc/pwd/lib_find_pwdfile.c @@ -37,7 +37,7 @@ ****************************************************************************/ typedef CODE int (pwd_foreach_match_t)(FAR const struct passwd *entry, - uintptr_t arg); + uintptr_t index, uintptr_t arg); /**************************************************************************** * Private Functions @@ -52,6 +52,7 @@ typedef CODE int (pwd_foreach_match_t)(FAR const struct passwd *entry, * * Input Parameters: * entry - The parsed passwd file record + * index - The index of record in passwd file * arg - A pointer to the user name to match * * Returned Value: @@ -61,8 +62,11 @@ typedef CODE int (pwd_foreach_match_t)(FAR const struct passwd *entry, * ****************************************************************************/ -static int pwd_match_name(FAR const struct passwd *entry, uintptr_t arg) +static int pwd_match_name(FAR const struct passwd *entry, + uintptr_t index, uintptr_t arg) { + UNUSED(index); + FAR const char *uname = (FAR const char *)arg; return strcmp(entry->pw_name, uname) == 0 ? 1 : 0; } @@ -76,6 +80,7 @@ static int pwd_match_name(FAR const struct passwd *entry, uintptr_t arg) * * Input Parameters: * entry - The parsed passwd file record + * index - The index of record in passwd file * arg - The user ID to match * * Returned Value: @@ -85,12 +90,41 @@ static int pwd_match_name(FAR const struct passwd *entry, uintptr_t arg) * ****************************************************************************/ -static int pwd_match_uid(FAR const struct passwd *entry, uintptr_t arg) +static int pwd_match_uid(FAR const struct passwd *entry, + uintptr_t index, uintptr_t arg) { + UNUSED(index); + int match_uid = (int)arg; return match_uid == entry->pw_uid ? 1 : 0; } +/**************************************************************************** + * Name: pwd_match_index + * + * Description: + * Called for each record in the passwd file. Returns "1" if the record + * matches the index (passed as arg) + * + * Input Parameters: + * entry - The parsed passwd file record + * index - The index of record in passwd file + * arg - The index to match + * + * Returned Value: + * = 0 : No entry name does not match. + * = 1 : The entry name matches + * + ****************************************************************************/ + +static int pwd_match_index(FAR const struct passwd *entry, + uintptr_t index, uintptr_t arg) +{ + UNUSED(entry); + + return index == arg; +} + /**************************************************************************** * Name: pwd_foreach * @@ -118,6 +152,7 @@ static int pwd_foreach(pwd_foreach_match_t match, uintptr_t arg, FAR FILE *stream; FAR char *ptr; FAR char *save; + int index = 0; int ret; stream = fopen(CONFIG_LIBC_PASSWD_FILEPATH, "r"); @@ -255,7 +290,7 @@ static int pwd_foreach(pwd_foreach_match_t match, uintptr_t arg, /* Check for a match */ - ret = match(entry, arg); + ret = match(entry, (uintptr_t)index++, arg); if (ret != 0) { /* We either have the match or an error occurred. */ @@ -333,3 +368,29 @@ int pwd_findby_uid(uid_t uid, FAR struct passwd *entry, FAR char *buffer, return pwd_foreach(pwd_match_uid, (uintptr_t)uid, entry, buffer, buflen); } + +/**************************************************************************** + * Name: pwd_findby_index + * + * Description: + * Find passwd file entry using the index. + * + * Input Parameters: + * index - The index of entry + * entry - Location to return the parsed passwd file entry + * buffer - I/O buffer used to access the passwd file + * buflen - The size of the I/O buffer in bytes + * + * Returned Value: + * < 0 : An error has occurred. + * = 0 : No entry with this name was found. + * = 1 : The entry with this name was found. + * + ****************************************************************************/ + +int pwd_findby_index(int index, FAR struct passwd *entry, + FAR char *buffer, size_t buflen) +{ + return pwd_foreach(pwd_match_index, (uintptr_t)index, + entry, buffer, buflen); +} diff --git a/libs/libc/pwd/lib_getpwent.c b/libs/libc/pwd/lib_getpwent.c new file mode 100644 index 0000000000..53ac0808fe --- /dev/null +++ b/libs/libc/pwd/lib_getpwent.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * libs/libc/pwd/lib_getpwent.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pwd/lib_pwd.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setpwent + * + * Description: + * The setpwent() function rewinds to the beginning of the password + * database. + * + * Input Parameters: + * None. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void setpwent(void) +{ + g_passwd_index = 0; +} + +/**************************************************************************** + * Name: endpwent + * + * Description: + * The endpwent() function is used to close the password database after + * all processing has been performed. + * + * Input Parameters: + * None. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void endpwent(void) +{ + g_passwd_index = 0; +} + +/**************************************************************************** + * Name: getpwent + * + * Description: + * The getpwent() function returns a pointer to a structure + * containing the broken-out fields of a record from the password + * database. + * + * Input Parameters: + * None. + * + * Returned Value: + * The getpwent() function returns a pointer to a passwd structure, + * or NULL if there are no more entries or an error occurred. If an + * error occurs, errno is set to indicate the error. If one wants + * to check errno after the call, it should be set to zero before + * the call. + * + ****************************************************************************/ + +FAR struct passwd *getpwent(void) +{ + FAR struct passwd *pwd; + getpwent_r(&g_passwd, g_passwd_buffer, + CONFIG_LIBC_PASSWD_LINESIZE, &pwd); + return pwd; +} + +/**************************************************************************** + * Name: getpwent_r + * + * Description: + * The functions getpwent_r() are the reentrant versions of getpwent(). + * The former reads the next passwd entry from the stream + * initialized by setpwent(). + * + * Input Parameters: + * pwd - contains the struct passwd that was read from the stream, + * if any. + * buf - contains additional strings, if any. + * buflen - specifies the size of buf. + * *result - returns a pointer to the struct passwd in *pwd. + * + * Returned Value: + * On success, return 0, and *pwbufp shall contain a pointer to the result. + * On failure, *pwbufp shall contain NULL. return an error an follows: + * ENOENT: No more password entries. + * ERANGE: Not enough buffer space. Specify a larger buffer and + * try again. + * + ****************************************************************************/ + +int getpwent_r(FAR struct passwd *pwd, + FAR char *buf, size_t buflen, + FAR struct passwd **result) +{ + int ret; +#ifdef CONFIG_LIBC_PASSWD_FILE + ret = pwd_findby_index(g_passwd_index, pwd, buf, buflen); + if (ret != 1) + { + *result = NULL; + return ret < 0 ? ret : ENOENT; + } + + *result = pwd; + g_passwd_index++; + return OK; +#else + if (g_passwd_index != 0) + { + /* The only known user is 'root', if index in not 0. Thus, report + * back that no match was found. + */ + + *result = NULL; + return ENOENT; + } + + ret = getpwbuf_r(ROOT_UID, ROOT_GID, ROOT_NAME, ROOT_NAME, ROOT_DIR, + ROOT_SHELL, pwd, buf, buflen, result); + if (ret == 0) + { + g_passwd_index++; + } + + return ret; +#endif +} diff --git a/libs/libc/pwd/lib_pwd.h b/libs/libc/pwd/lib_pwd.h index 582616c3ee..5b73a2e14b 100644 --- a/libs/libc/pwd/lib_pwd.h +++ b/libs/libc/pwd/lib_pwd.h @@ -58,6 +58,7 @@ extern "C" /* Data for non-reentrant group functions */ +EXTERN int g_passwd_index; EXTERN struct passwd g_passwd; EXTERN char g_passwd_buffer[CONFIG_LIBC_PASSWD_LINESIZE]; @@ -78,6 +79,8 @@ int pwd_findby_name(FAR const char *uname, FAR struct passwd *entry, FAR char *buffer, size_t buflen); int pwd_findby_uid(uid_t uid, FAR struct passwd *entry, FAR char *buffer, size_t buflen); +int pwd_findby_index(int index, FAR struct passwd *entry, + FAR char *buffer, size_t buflen) #endif #undef EXTERN diff --git a/libs/libc/pwd/lib_pwd_globals.c b/libs/libc/pwd/lib_pwd_globals.c index 12deca175a..f6488d60e7 100644 --- a/libs/libc/pwd/lib_pwd_globals.c +++ b/libs/libc/pwd/lib_pwd_globals.c @@ -32,6 +32,7 @@ /* Data for non-reentrant group functions */ +int g_passwd_index; struct passwd g_passwd; char g_passwd_buffer[CONFIG_LIBC_PASSWD_LINESIZE];