Skip to content

Commit

Permalink
Add missing comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
Galfurian committed Oct 28, 2024
1 parent f5a4d9a commit a386be3
Show file tree
Hide file tree
Showing 18 changed files with 689 additions and 927 deletions.
457 changes: 239 additions & 218 deletions doc/CMakeLists.txt

Large diffs are not rendered by default.

49 changes: 43 additions & 6 deletions libc/inc/err.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,51 @@

#include <stdarg.h>

/// @brief Print formatted error message on stderr and exit
/// @param eval The exit value.
/// @param fmt The format string.
/// @brief Print a formatted error message on stderr and exit the program.
///
/// @details This function prints an error message to stderr, formatted
/// according to the given format string, followed by a system error message if
/// applicable. It then terminates the program with the specified exit value.
/// This is typically used when a system call fails.
///
/// @param eval The exit value to use when terminating the program.
/// @param fmt The format string for the error message.
void err(int eval, const char *fmt, ...);

/// @brief Print a formatted error message on stderr using a va_list and exit
/// the program.
///
/// @details This function is similar to `err()`, but accepts a `va_list` to
/// support variable arguments. This allows you to pass a list of arguments that
/// can be formatted into the error message. The program exits with the
/// specified exit value.
///
/// @param eval The exit value to use when terminating the program.
/// @param fmt The format string for the error message.
/// @param args The variable argument list.
void verr(int eval, const char *fmt, va_list args);

/// @brief Print formatted message on stderr without appending an error message and exit
/// @param eval The exit value.
/// @param fmt The format string.
/// @brief Print a formatted message on stderr without appending an error
/// message and exit.
///
/// @details This function prints a formatted message to stderr without
/// appending a system error message (such as those related to errno). It then
/// terminates the program with the specified exit value. This is useful when
/// the error isn't related to a system call failure but requires exiting the
/// program.
///
/// @param eval The exit value to use when terminating the program.
/// @param fmt The format string for the message.
void errx(int eval, const char *fmt, ...);

/// @brief Print a formatted message on stderr using a va_list and exit without
/// appending an error message.
///
/// @details This function is similar to `errx()`, but accepts a `va_list` to
/// handle variable arguments. It prints the formatted message and exits the
/// program without appending a system error message.
///
/// @param eval The exit value to use when terminating the program.
/// @param fmt The format string for the message.
/// @param args The variable argument list.
void verrx(int eval, const char *fmt, va_list args);
58 changes: 44 additions & 14 deletions libc/inc/shadow.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,52 @@
// @file shadow.h
/// @brief Secret password file routines
/// @file shadow.h
/// @brief Defines structures and functions for working with the shadow password
/// file.
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.

#pragma once

#include "stddef.h"

#define SHADOW "/etc/shadow"
#define SHADOW "/etc/shadow" ///< Path to the shadow password file.

/// @brief Structure representing a shadow password record.
/// @details This structure is used to store details from the shadow password
/// file (`/etc/shadow`), including information such as the user's encrypted
/// password and password change policies.
struct spwd {
char *sp_namp; ///< user login name.
char *sp_pwdp; ///< encrypted password.
long int sp_lstchg; ///< last password change.
long int sp_min; ///< days until change allowed.
long int sp_max; ///< days before change required.
long int sp_warn; ///< days warning for expiration.
long int sp_inact; ///< days before account inactive.
long int sp_expire; ///< date when account expires.
unsigned long int sp_flag; ///< reserved for future use.
char *sp_namp; ///< User login name.
char *sp_pwdp; ///< Encrypted password.
long int sp_lstchg; ///< Date of the last password change, in days since the epoch.
long int sp_min; ///< Minimum number of days until the next password change is allowed.
long int sp_max; ///< Maximum number of days before a password change is required.
long int sp_warn; ///< Number of days before the password expires to warn the user.
long int sp_inact; ///< Number of days after expiration until the account is considered inactive.
long int sp_expire; ///< Date when the account expires, in days since the epoch.
unsigned long int sp_flag; ///< Reserved for future use.
};

struct spwd *getspnam(const char *);
int getspnam_r(const char *, struct spwd *, char *, size_t, struct spwd **);
/// @brief Retrieves a shadow password record by username.
///
/// @details This function retrieves the shadow password entry for a specific
/// user from the shadow password file (`/etc/shadow`). It uses a static buffer
/// to store the result, which is overwritten on each call.
///
/// @param name The login name of the user to search for.
/// @return Pointer to the `spwd` structure with the user's shadow password entry, or NULL if not found.
struct spwd *getspnam(const char * name);

/// @brief Retrieves a shadow password record by username (reentrant version).
///
/// @details This function retrieves the shadow password entry for a specific
/// user in a reentrant manner. It stores the result in user-provided buffers to
/// avoid race conditions. This is the safer, thread-safe version of
/// `getspnam()`.
///
/// @param name The login name of the user to search for.
/// @param spwd_buf Pointer to a user-provided `spwd` structure where the result will be stored.
/// @param buf Buffer to hold additional string data like the encrypted password.
/// @param buflen Size of the buffer provided.
/// @param result Pointer to the result. On success, this will point to `spwd_buf`, or NULL on failure.
/// @return 0 on success, or a non-zero error code on failure.
int getspnam_r(const char *name, struct spwd *spwd_buf, char *buf, size_t buflen, struct spwd **result);
22 changes: 0 additions & 22 deletions libc/inc/sys/mman.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#define MAP_SHARED 0x01 ///< The memory is shared.
#define MAP_PRIVATE 0x02 ///< The memory is private.

#ifndef __KERNEL__

/// @brief creates a new mapping in the virtual address space of the calling process.
/// @param addr the starting address for the new mapping.
/// @param length specifies the length of the mapping (which must be greater than 0).
Expand All @@ -31,23 +29,3 @@ void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
/// @param length the length of the mapped area.
/// @return 0 on success, -1 on falure and errno is set.
int munmap(void *addr, size_t length);

#else

/// @brief creates a new mapping in the virtual address space of the calling process.
/// @param addr the starting address for the new mapping.
/// @param length specifies the length of the mapping (which must be greater than 0).
/// @param prot describes the desired memory protection of the mapping (and must not conflict with the open mode of the file).
/// @param flags determines whether updates to the mapping are visible to other processes mapping the same region.
/// @param fd in case of file mapping, the file descriptor to use.
/// @param offset offset in the file, which must be a multiple of the page size PAGE_SIZE.
/// @return returns a pointer to the mapped area, -1 and errno is set.
void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

/// @brief deletes the mappings for the specified address range.
/// @param addr the starting address.
/// @param length the length of the mapped area.
/// @return 0 on success, -1 on falure and errno is set.
int sys_munmap(void *addr, size_t length);

#endif
3 changes: 2 additions & 1 deletion libc/inc/sys/sem.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
#define SEM_STAT 18 ///< Return a semid_ds structure.
#define SEM_INFO 19 ///< Return a seminfo structure.

/// }@
/// @}

/// @brief Defines the maximum number of semaphores in a semaphore set.
#define SEM_SET_MAX 256

/// @brief Optional argument for semctl() function
Expand Down
200 changes: 112 additions & 88 deletions libc/src/shadow.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/// @file shadow.c
/// @brief
/// @brief Functions for handling the shadow password file (`/etc/shadow`).
/// @copyright (c) 2005-2020 Rich Felker, et al.
/// This file is based on the code from libmusl.

#include <shadow.h>
#include <fcntl.h>
#include <stdio.h>
Expand All @@ -12,103 +13,126 @@
#include <sys/stat.h>
#include <ctype.h>

/// Defines the buffer size for reading lines from the shadow file.
#define LINE_LIM 256

/// @brief Converts a string to a long integer.
///
/// @details Parses a string into a long integer and advances the string pointer.
/// If the string starts with a colon or newline, returns -1.
///
/// @param s Pointer to the string to convert.
/// @return The parsed long integer.
static long xatol(char **s)
{
long x;
if (**s == ':' || **s == '\n') return -1;
for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0');
return x;
long x;
if (**s == ':' || **s == '\n') return -1;
for (x = 0; **s - '0' < 10U; ++*s) x = 10 * x + (**s - '0');
return x;
}

/// @brief Parses a shadow password entry from a string.
///
/// @details This function parses a line from the shadow password file into a `spwd` structure.
/// The fields in the shadow password file are separated by colons.
///
/// @param s The string containing the shadow password entry.
/// @param sp Pointer to the `spwd` structure where the parsed data will be stored.
/// @return 0 on success, -1 on failure.
int __parsespent(char *s, struct spwd *sp)
{
sp->sp_namp = s;
if (!(s = strchr(s, ':'))) return -1;
*s = 0;

sp->sp_pwdp = ++s;
if (!(s = strchr(s, ':'))) return -1;
*s = 0;

s++; sp->sp_lstchg = xatol(&s);
if (*s != ':') return -1;

s++; sp->sp_min = xatol(&s);
if (*s != ':') return -1;

s++; sp->sp_max = xatol(&s);
if (*s != ':') return -1;

s++; sp->sp_warn = xatol(&s);
if (*s != ':') return -1;

s++; sp->sp_inact = xatol(&s);
if (*s != ':') return -1;

s++; sp->sp_expire = xatol(&s);
if (*s != ':') return -1;

s++; sp->sp_flag = xatol(&s);
if (*s != '\n') return -1;
return 0;
sp->sp_namp = s;
if (!(s = strchr(s, ':'))) return -1;
*s = 0;

sp->sp_pwdp = ++s;
if (!(s = strchr(s, ':'))) return -1;
*s = 0;

s++;
sp->sp_lstchg = xatol(&s);
if (*s != ':') return -1;

s++;
sp->sp_min = xatol(&s);
if (*s != ':') return -1;

s++;
sp->sp_max = xatol(&s);
if (*s != ':') return -1;

s++;
sp->sp_warn = xatol(&s);
if (*s != ':') return -1;

s++;
sp->sp_inact = xatol(&s);
if (*s != ':') return -1;

s++;
sp->sp_expire = xatol(&s);
if (*s != ':') return -1;

s++;
sp->sp_flag = xatol(&s);
if (*s != '\n') return -1;
return 0;
}

int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct spwd **res)
struct spwd *getspnam(const char *name)
{
char path[20+NAME_MAX];
int rv = 0;
int fd;
size_t k, l = strlen(name);
int skip = 0;
int cs;
int orig_errno = errno;

*res = 0;

/* Disallow potentially-malicious user names */
if (*name=='.' || strchr(name, '/') || !l)
return errno = EINVAL;

/* Buffer size must at least be able to hold name, plus some.. */
if (size < l+100)
return errno = ERANGE;

fd = open(SHADOW, O_RDONLY, 0);
if (fd < 0) {
return errno;
}

while (fgets(buf, size, fd) && (k=strlen(buf))>0) {
if (skip || strncmp(name, buf, l) || buf[l]!=':') {
skip = buf[k-1] != '\n';
continue;
}
if (buf[k-1] != '\n') {
rv = ERANGE;
break;
}

if (__parsespent(buf, sp) < 0) continue;
*res = sp;
break;
}
errno = rv ? rv : orig_errno;
return rv;
static struct spwd spwd_buf;
static char *line;
struct spwd *result;
int e;
int orig_errno = errno;

if (!line) line = malloc(LINE_LIM);
if (!line) return 0;
e = getspnam_r(name, &spwd_buf, line, LINE_LIM, &result);
errno = e ? e : orig_errno;
return result;
}

#define LINE_LIM 256

struct spwd *getspnam(const char *name)
int getspnam_r(const char *name, struct spwd *spwd_buf, char *buf, size_t buflen, struct spwd **result)
{
static struct spwd sp;
static char *line;
struct spwd *res;
int e;
int orig_errno = errno;

if (!line) line = malloc(LINE_LIM);
if (!line) return 0;
e = getspnam_r(name, &sp, line, LINE_LIM, &res);
errno = e ? e : orig_errno;
return res;
char path[20 + NAME_MAX];
int rv = 0;
int fd;
size_t k, l = strlen(name);
int skip = 0;
int cs;
int orig_errno = errno;

*result = 0;

/* Disallow potentially-malicious user names */
if (*name == '.' || strchr(name, '/') || !l)
return errno = EINVAL;

/* Buffer size must at least be able to hold name, plus some.. */
if (buflen < l + 100)
return errno = ERANGE;

fd = open(SHADOW, O_RDONLY, 0);
if (fd < 0) {
return errno;
}

while (fgets(buf, buflen, fd) && (k = strlen(buf)) > 0) {
if (skip || strncmp(name, buf, l) || buf[l] != ':') {
skip = buf[k - 1] != '\n';
continue;
}
if (buf[k - 1] != '\n') {
rv = ERANGE;
break;
}

if (__parsespent(buf, spwd_buf) < 0) continue;
*result = spwd_buf;
break;
}
errno = rv ? rv : orig_errno;
return rv;
}
Loading

0 comments on commit a386be3

Please sign in to comment.