Merge branch 'release/v0.5.0'
This commit is contained in:
@@ -143,6 +143,7 @@ set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -drive file=${CMAKE_BINARY_DIR}/rootfs.img,
|
||||
# This first target runs the emualtor passing the kernel binary file.
|
||||
add_custom_target(
|
||||
qemu
|
||||
COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem"
|
||||
COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -kernel ${CMAKE_BINARY_DIR}/mentos/kernel-bootloader.bin
|
||||
DEPENDS kernel-bootloader.bin
|
||||
)
|
||||
@@ -174,6 +175,7 @@ add_custom_target(
|
||||
# debug mode, and pause it up until a debugger connects to it.
|
||||
add_custom_target(
|
||||
qemu-gdb
|
||||
COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem"
|
||||
COMMAND echo "\n\n"
|
||||
COMMAND echo "Now, QEMU has loaded the kernel, and it is waiting that you\n"
|
||||
COMMAND echo "remotely connect to it. To start debugging, open a new shell\n"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
NAME
|
||||
ls - list directory contents
|
||||
|
||||
SYNOPSIS
|
||||
ls [OPTIONS] [FILE/FOLDER]
|
||||
|
||||
DESCRIPTION
|
||||
List information about the given file, or the files contained in the given
|
||||
folder. If not argument is provided it will list information about files
|
||||
inside the current folder.
|
||||
|
||||
OPTIONS
|
||||
-a : list all entries.
|
||||
-l : show the entries as a detailed list.
|
||||
@@ -35,8 +35,3 @@ int __libc_start_main(int (*main)(int, char **, char **), int argc, char *argv[]
|
||||
//dbg_print("== END %-30s =======================================\n", argv[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
// WARNING: This declaration must be here, because libc_start is compiled
|
||||
// with all the programs, and all the programs NEED to have the `sigreturn`
|
||||
// symbol. It must be this way, period.
|
||||
_syscall0(int, sigreturn)
|
||||
|
||||
@@ -162,6 +162,7 @@ int getpwnam_r(const char *name, passwd_t *pwd, char *buf, size_t buflen, passwd
|
||||
// Return success.
|
||||
return 1;
|
||||
}
|
||||
errno = ENOENT;
|
||||
// Close the file.
|
||||
close(fd);
|
||||
// Return fail.
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include "signal.h"
|
||||
#include "sys/bitops.h"
|
||||
|
||||
_syscall0(int, sigreturn)
|
||||
|
||||
_syscall3(int, sigprocmask, int, how, const sigset_t *, set, sigset_t *, oldset)
|
||||
|
||||
static const char *sys_siglist[] = {
|
||||
"HUP",
|
||||
"INT",
|
||||
@@ -45,11 +49,19 @@ static const char *sys_siglist[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
_syscall2(sighandler_t, signal, int, signum, sighandler_t, handler)
|
||||
sighandler_t signal(int signum, sighandler_t handler)
|
||||
{
|
||||
long __res;
|
||||
__inline_syscall3(__res, signal, signum, handler, (unsigned int)sigreturn);
|
||||
__syscall_return(sighandler_t, __res);
|
||||
}
|
||||
|
||||
_syscall3(int, sigaction, int, signum, const sigaction_t *, act, sigaction_t *, oldact)
|
||||
|
||||
_syscall3(int, sigprocmask, int, how, const sigset_t *, set, sigset_t *, oldset)
|
||||
int sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
|
||||
{
|
||||
long __res;
|
||||
__inline_syscall4(__res, sigaction, signum, act, oldact, (unsigned int)sigreturn);
|
||||
__syscall_return(int, __res);
|
||||
}
|
||||
|
||||
const char *strsignal(int sig)
|
||||
{
|
||||
|
||||
@@ -119,9 +119,8 @@ typedef struct task_struct {
|
||||
/// The current working directory.
|
||||
char cwd[PATH_MAX];
|
||||
|
||||
// struct signal_struct *signal;
|
||||
/// Instruction Pointer of the LIBC Signal Handler.
|
||||
uint32_t sigreturn_eip;
|
||||
/// Address of the LIBC sigreturn function.
|
||||
uint32_t sigreturn_addr;
|
||||
/// Pointer to the process’s signal handler descriptor
|
||||
sighand_t sighand;
|
||||
/// Mask of blocked signals.
|
||||
|
||||
@@ -269,14 +269,14 @@ int sys_kill(pid_t pid, int sig);
|
||||
/// @param signum The signal number.
|
||||
/// @param handler The handler for the signal.
|
||||
/// @return The previous value of the signal handler, or SIG_ERR on error.
|
||||
sighandler_t sys_signal(int signum, sighandler_t handler);
|
||||
sighandler_t sys_signal(int signum, sighandler_t handler, uint32_t sigreturn_addr);
|
||||
|
||||
/// @brief Examine and change a signal action.
|
||||
/// @param signum Specifies the signal and can be any valid signal except SIGKILL and SIGSTOP.
|
||||
/// @param act If non-NULL, the new action for signal signum is installed from act.
|
||||
/// @param oldact If non-NULL, the previous action is saved in oldact.
|
||||
/// @return returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.
|
||||
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact);
|
||||
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact, uint32_t sigreturn_addr);
|
||||
|
||||
/// @brief Examine and change blocked signals.
|
||||
/// @param how Determines the behavior of the call.
|
||||
|
||||
@@ -222,17 +222,6 @@ static inline void elf_dump_symbol_table(elf_header_t *header)
|
||||
// EXEC-RELATED FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
static inline int elf_set_sigreturn(elf_header_t *header, task_struct *task)
|
||||
{
|
||||
elf_symbol_t *sigreturn = elf_find_symbol(header, "sigreturn");
|
||||
if (sigreturn == NULL) {
|
||||
pr_err("Failed to find `sigreturn`!\n");
|
||||
return false;
|
||||
}
|
||||
task->sigreturn_eip = sigreturn->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Loads an ELF executable.
|
||||
/// @param task The task for which we load the ELF.
|
||||
/// @param file The ELF file.
|
||||
@@ -311,11 +300,6 @@ int elf_load_file(task_struct *task, vfs_file_t *file, uint32_t *entry)
|
||||
pr_err("Elf file is not an executable.\n");
|
||||
goto return_error_free_buffer;
|
||||
}
|
||||
// Set the sigreturn of the task.
|
||||
if (!elf_set_sigreturn(header, task)) {
|
||||
pr_err("Failed to set `sigreturn` for the executable.\n");
|
||||
goto return_error_free_buffer;
|
||||
}
|
||||
if (!elf_load_exec(header, task)) {
|
||||
pr_err("Failed to load the executable.\n");
|
||||
goto return_error_free_buffer;
|
||||
|
||||
+103
-70
@@ -386,7 +386,6 @@ static int ext2_mkdir(const char *path, mode_t mode);
|
||||
static int ext2_rmdir(const char *path);
|
||||
static int ext2_stat(const char *path, stat_t *stat);
|
||||
static vfs_file_t *ext2_creat(const char *path, mode_t permission);
|
||||
|
||||
static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path);
|
||||
|
||||
// ============================================================================
|
||||
@@ -430,6 +429,28 @@ static const char *uuid_to_string(uint8_t uuid[16])
|
||||
return s;
|
||||
}
|
||||
|
||||
/// @brief Turns an ext2_file_type to string.
|
||||
/// @param ext2_type the ext2_file_type to turn to string.
|
||||
/// @return the string representing the ext2_file_type.
|
||||
static const char *ext2_file_type_to_string(ext2_file_type_t ext2_type)
|
||||
{
|
||||
if (ext2_type == ext2_file_type_regular_file)
|
||||
return "REG";
|
||||
if (ext2_type == ext2_file_type_directory)
|
||||
return "DIR";
|
||||
if (ext2_type == ext2_file_type_character_device)
|
||||
return "CHR";
|
||||
if (ext2_type == ext2_file_type_block_device)
|
||||
return "BLK";
|
||||
if (ext2_type == ext2_file_type_named_pipe)
|
||||
return "FIFO";
|
||||
if (ext2_type == ext2_file_type_socket)
|
||||
return "SOCK";
|
||||
if (ext2_type == ext2_file_type_symbolic_link)
|
||||
return "LNK";
|
||||
return "UNK";
|
||||
}
|
||||
|
||||
static int ext2_file_type_to_vfs_file_type(int ext2_type)
|
||||
{
|
||||
if (ext2_type == ext2_file_type_regular_file)
|
||||
@@ -502,63 +523,63 @@ static bool_t ext2_valid_permissions(int flags, mode_t mask, uid_t uid, gid_t gi
|
||||
/// @param sb the object to dump.
|
||||
static void ext2_dump_superblock(ext2_superblock_t *sb)
|
||||
{
|
||||
pr_debug("inodes_count : %d\n", sb->inodes_count);
|
||||
pr_debug("blocks_count : %d\n", sb->blocks_count);
|
||||
pr_debug("r_blocks_count : %d\n", sb->r_blocks_count);
|
||||
pr_debug("free_blocks_count : %d\n", sb->free_blocks_count);
|
||||
pr_debug("free_inodes_count : %d\n", sb->free_inodes_count);
|
||||
pr_debug("first_data_block : %d\n", sb->first_data_block);
|
||||
pr_debug("log_block_size : %d\n", sb->log_block_size);
|
||||
pr_debug("log_frag_size : %d\n", sb->log_frag_size);
|
||||
pr_debug("blocks_per_group : %d\n", sb->blocks_per_group);
|
||||
pr_debug("frags_per_group : %d\n", sb->frags_per_group);
|
||||
pr_debug("inodes_per_group : %d\n", sb->inodes_per_group);
|
||||
pr_debug("inodes_count : %u\n", sb->inodes_count);
|
||||
pr_debug("blocks_count : %u\n", sb->blocks_count);
|
||||
pr_debug("r_blocks_count : %u\n", sb->r_blocks_count);
|
||||
pr_debug("free_blocks_count : %u\n", sb->free_blocks_count);
|
||||
pr_debug("free_inodes_count : %u\n", sb->free_inodes_count);
|
||||
pr_debug("first_data_block : %u\n", sb->first_data_block);
|
||||
pr_debug("log_block_size : %u\n", sb->log_block_size);
|
||||
pr_debug("log_frag_size : %u\n", sb->log_frag_size);
|
||||
pr_debug("blocks_per_group : %u\n", sb->blocks_per_group);
|
||||
pr_debug("frags_per_group : %u\n", sb->frags_per_group);
|
||||
pr_debug("inodes_per_group : %u\n", sb->inodes_per_group);
|
||||
pr_debug("mtime : %s\n", time_to_string(sb->mtime));
|
||||
pr_debug("wtime : %s\n", time_to_string(sb->wtime));
|
||||
pr_debug("mnt_count : %d\n", sb->mnt_count);
|
||||
pr_debug("max_mnt_count : %d\n", sb->max_mnt_count);
|
||||
pr_debug("magic : 0x%0x\n", sb->magic);
|
||||
pr_debug("magic : 0x%0x (== 0x%0x)\n", sb->magic, EXT2_SUPERBLOCK_MAGIC);
|
||||
pr_debug("state : %d\n", sb->state);
|
||||
pr_debug("errors : %d\n", sb->errors);
|
||||
pr_debug("minor_rev_level : %d\n", sb->minor_rev_level);
|
||||
pr_debug("lastcheck : %s\n", time_to_string(sb->lastcheck));
|
||||
pr_debug("checkinterval : %d\n", sb->checkinterval);
|
||||
pr_debug("creator_os : %d\n", sb->creator_os);
|
||||
pr_debug("rev_level : %d\n", sb->rev_level);
|
||||
pr_debug("def_resuid : %d\n", sb->def_resuid);
|
||||
pr_debug("def_resgid : %d\n", sb->def_resgid);
|
||||
pr_debug("first_ino : %d\n", sb->first_ino);
|
||||
pr_debug("inode_size : %d\n", sb->inode_size);
|
||||
pr_debug("block_group_nr : %d\n", sb->block_group_nr);
|
||||
pr_debug("feature_compat : %d\n", sb->feature_compat);
|
||||
pr_debug("feature_incompat : %d\n", sb->feature_incompat);
|
||||
pr_debug("feature_ro_compat : %d\n", sb->feature_ro_compat);
|
||||
pr_debug("checkinterval : %u\n", sb->checkinterval);
|
||||
pr_debug("creator_os : %u\n", sb->creator_os);
|
||||
pr_debug("rev_level : %u\n", sb->rev_level);
|
||||
pr_debug("def_resuid : %u\n", sb->def_resuid);
|
||||
pr_debug("def_resgid : %u\n", sb->def_resgid);
|
||||
pr_debug("first_ino : %u\n", sb->first_ino);
|
||||
pr_debug("inode_size : %u\n", sb->inode_size);
|
||||
pr_debug("block_group_nr : %u\n", sb->block_group_nr);
|
||||
pr_debug("feature_compat : %u\n", sb->feature_compat);
|
||||
pr_debug("feature_incompat : %u\n", sb->feature_incompat);
|
||||
pr_debug("feature_ro_compat : %u\n", sb->feature_ro_compat);
|
||||
pr_debug("uuid : %s\n", uuid_to_string(sb->uuid));
|
||||
pr_debug("volume_name : %s\n", (char *)sb->volume_name);
|
||||
pr_debug("last_mounted : %s\n", (char *)sb->last_mounted);
|
||||
pr_debug("algo_bitmap : %d\n", sb->algo_bitmap);
|
||||
pr_debug("prealloc_blocks : %d\n", sb->prealloc_blocks);
|
||||
pr_debug("prealloc_dir_blocks : %d\n", sb->prealloc_dir_blocks);
|
||||
pr_debug("algo_bitmap : %u\n", sb->algo_bitmap);
|
||||
pr_debug("prealloc_blocks : %u\n", sb->prealloc_blocks);
|
||||
pr_debug("prealloc_dir_blocks : %u\n", sb->prealloc_dir_blocks);
|
||||
pr_debug("journal_uuid : %s\n", uuid_to_string(sb->journal_uuid));
|
||||
pr_debug("journal_inum : %d\n", sb->journal_inum);
|
||||
pr_debug("jounral_dev : %d\n", sb->jounral_dev);
|
||||
pr_debug("last_orphan : %d\n", sb->last_orphan);
|
||||
pr_debug("journal_inum : %u\n", sb->journal_inum);
|
||||
pr_debug("jounral_dev : %u\n", sb->jounral_dev);
|
||||
pr_debug("last_orphan : %u\n", sb->last_orphan);
|
||||
pr_debug("hash_seed : %u %u %u %u\n", sb->hash_seed[0], sb->hash_seed[1], sb->hash_seed[2], sb->hash_seed[3]);
|
||||
pr_debug("def_hash_version : %d\n", sb->def_hash_version);
|
||||
pr_debug("default_mount_options : %d\n", sb->default_mount_options);
|
||||
pr_debug("first_meta_bg : %d\n", sb->first_meta_block_group_id);
|
||||
pr_debug("def_hash_version : %u\n", sb->def_hash_version);
|
||||
pr_debug("default_mount_options : %u\n", sb->default_mount_options);
|
||||
pr_debug("first_meta_bg : %u\n", sb->first_meta_block_group_id);
|
||||
}
|
||||
|
||||
/// @brief Dumps on debugging output the group descriptor.
|
||||
/// @param gd the object to dump.
|
||||
static void ext2_dump_group_descriptor(ext2_group_descriptor_t *gd)
|
||||
{
|
||||
pr_debug("block_bitmap : %d\n", gd->block_bitmap);
|
||||
pr_debug("inode_bitmap : %d\n", gd->inode_bitmap);
|
||||
pr_debug("inode_table : %d\n", gd->inode_table);
|
||||
pr_debug("free_blocks_count : %d\n", gd->free_blocks_count);
|
||||
pr_debug("free_inodes_count : %d\n", gd->free_inodes_count);
|
||||
pr_debug("used_dirs_count : %d\n", gd->used_dirs_count);
|
||||
pr_debug("block_bitmap : %u\n", gd->block_bitmap);
|
||||
pr_debug("inode_bitmap : %u\n", gd->inode_bitmap);
|
||||
pr_debug("inode_table : %u\n", gd->inode_table);
|
||||
pr_debug("free_blocks_count : %u\n", gd->free_blocks_count);
|
||||
pr_debug("free_inodes_count : %u\n", gd->free_inodes_count);
|
||||
pr_debug("used_dirs_count : %u\n", gd->used_dirs_count);
|
||||
}
|
||||
|
||||
/// @brief Dumps on debugging output the inode.
|
||||
@@ -601,6 +622,13 @@ static void ext2_dump_inode(ext2_inode_t *inode)
|
||||
inode->generation, inode->file_acl, inode->dir_acl);
|
||||
}
|
||||
|
||||
/// @brief Dumps on debugging output the dirent.
|
||||
/// @param dirent the object to dump.
|
||||
static void ext2_dump_dirent(ext2_dirent_t *dirent)
|
||||
{
|
||||
pr_debug("Inode: %4u Rec. Len.: %4u Name Len.: %4u Type:%4s Name: %s\n", dirent->inode, dirent->rec_len, dirent->name_len, ext2_file_type_to_string(dirent->file_type), dirent->name);
|
||||
}
|
||||
|
||||
/// @brief Dumps on debugging output the BGDT.
|
||||
/// @param fs the filesystem of which we print the BGDT.
|
||||
static void ext2_dump_bgdt(ext2_filesystem_t *fs)
|
||||
@@ -612,21 +640,21 @@ static void ext2_dump_bgdt(ext2_filesystem_t *fs)
|
||||
for (uint32_t i = 0; i < fs->block_groups_count; ++i) {
|
||||
// Get the pointer to the current group descriptor.
|
||||
ext2_group_descriptor_t *gd = &(fs->block_groups[i]);
|
||||
pr_debug("Block Group Descriptor [%d] @ %d:\n", i, fs->bgdt_start_block + i * fs->superblock.blocks_per_group);
|
||||
pr_debug(" block_bitmap : %d\n", gd->block_bitmap);
|
||||
pr_debug(" inode_bitmap : %d\n", gd->inode_bitmap);
|
||||
pr_debug(" inode_table : %d\n", gd->inode_table);
|
||||
pr_debug(" Used Dirs : %d\n", gd->used_dirs_count);
|
||||
pr_debug(" Free Blocks : %4d of %d\n", gd->free_blocks_count, fs->superblock.blocks_per_group);
|
||||
pr_debug(" Free Inodes : %4d of %d\n", gd->free_inodes_count, fs->superblock.inodes_per_group);
|
||||
pr_debug("Block Group Descriptor [%u] @ %u:\n", i, fs->bgdt_start_block + i * fs->superblock.blocks_per_group);
|
||||
pr_debug(" block_bitmap : %u\n", gd->block_bitmap);
|
||||
pr_debug(" inode_bitmap : %u\n", gd->inode_bitmap);
|
||||
pr_debug(" inode_table : %u\n", gd->inode_table);
|
||||
pr_debug(" Used Dirs : %u\n", gd->used_dirs_count);
|
||||
pr_debug(" Free Blocks : %4u of %u\n", gd->free_blocks_count, fs->superblock.blocks_per_group);
|
||||
pr_debug(" Free Inodes : %4u of %u\n", gd->free_inodes_count, fs->superblock.inodes_per_group);
|
||||
// Dump the block bitmap.
|
||||
ext2_read_block(fs, gd->block_bitmap, cache);
|
||||
pr_debug(" Block Bitmap at %d\n", gd->block_bitmap);
|
||||
pr_debug(" Block Bitmap at %u\n", gd->block_bitmap);
|
||||
for (uint32_t j = 0; j < fs->block_size; ++j) {
|
||||
if ((j % 8) == 0)
|
||||
pr_debug(" Block index: %4d, Bitmap: %s\n", j / 8, dec_to_binary(cache[j / 8], 8));
|
||||
pr_debug(" Block index: %4u, Bitmap: %s\n", j / 8, dec_to_binary(cache[j / 8], 8));
|
||||
if (!ext2_check_bitmap_bit(cache, j)) {
|
||||
pr_debug(" First free block in group is in block %d, the linear index is %d\n", j / 8, j);
|
||||
pr_debug(" First free block in group is in block %u, the linear index is %u\n", j / 8, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -674,6 +702,7 @@ static void ext2_dump_filesystem(ext2_filesystem_t *fs)
|
||||
/// @details Remember that inode addressing starts from 1.
|
||||
static uint32_t ext2_get_group_index_from_inode(ext2_filesystem_t *fs, uint32_t inode_index)
|
||||
{
|
||||
assert(inode_index != 0 && "Your are trying to access inode 0.");
|
||||
return (inode_index - 1) / fs->superblock.inodes_per_group;
|
||||
}
|
||||
|
||||
@@ -684,6 +713,7 @@ static uint32_t ext2_get_group_index_from_inode(ext2_filesystem_t *fs, uint32_t
|
||||
/// @details Remember that inode addressing starts from 1.
|
||||
static uint32_t ext2_get_inode_offest_in_group(ext2_filesystem_t *fs, uint32_t inode_index)
|
||||
{
|
||||
assert(inode_index != 0 && "Your are trying to access inode 0.");
|
||||
return (inode_index - 1) % fs->superblock.inodes_per_group;
|
||||
}
|
||||
|
||||
@@ -852,7 +882,6 @@ static int ext2_write_superblock(ext2_filesystem_t *fs)
|
||||
/// @return the amount of data we read, or negative value for an error.
|
||||
static int ext2_read_block(ext2_filesystem_t *fs, uint32_t block_index, uint8_t *buffer)
|
||||
{
|
||||
//pr_debug("Read block %4d for EXT2 filesystem (0x%x)\n", block_index, fs);
|
||||
if (block_index == 0) {
|
||||
pr_err("You are trying to read an invalid block index (%d).\n", block_index);
|
||||
return -1;
|
||||
@@ -871,7 +900,6 @@ static int ext2_read_block(ext2_filesystem_t *fs, uint32_t block_index, uint8_t
|
||||
/// @return the amount of data we wrote, or negative value for an error.
|
||||
static int ext2_write_block(ext2_filesystem_t *fs, uint32_t block_index, uint8_t *buffer)
|
||||
{
|
||||
//pr_debug("Write block %4d for EXT2 filesystem (0x%x)\n", block_index, fs);
|
||||
if (block_index == 0) {
|
||||
pr_err("You are trying to write on an invalid block index (%d).\n", block_index);
|
||||
return -1;
|
||||
@@ -920,30 +948,33 @@ static int ext2_write_bgdt(ext2_filesystem_t *fs)
|
||||
/// @return 0 on success, -1 on failure.
|
||||
static int ext2_read_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t inode_index)
|
||||
{
|
||||
uint32_t group_index, block_index, inode_offset;
|
||||
if (inode_index == 0) {
|
||||
pr_err("You are trying to read an invalid inode index (%d).\n", inode_index);
|
||||
return -1;
|
||||
}
|
||||
// Retrieve the group index.
|
||||
uint32_t group_index = ext2_get_group_index_from_inode(fs, inode_index);
|
||||
group_index = ext2_get_group_index_from_inode(fs, inode_index);
|
||||
if (group_index > fs->block_groups_count) {
|
||||
pr_err("Invalid group index computed from inode index `%d`.\n", inode_index);
|
||||
return -1;
|
||||
}
|
||||
// Get the index of the inode inside the group.
|
||||
uint32_t offset = ext2_get_inode_offest_in_group(fs, inode_index);
|
||||
inode_offset = ext2_get_inode_offest_in_group(fs, inode_index);
|
||||
// Get the block offest.
|
||||
uint32_t block = ext2_get_block_index_from_inode_offset(fs, offset);
|
||||
block_index = ext2_get_block_index_from_inode_offset(fs, inode_offset);
|
||||
// Get the real inode offset inside the block.
|
||||
offset %= fs->inodes_per_block_count;
|
||||
inode_offset %= fs->inodes_per_block_count;
|
||||
// Log the address to the inode.
|
||||
pr_debug("Read inode (inode:%4u block:%4u offset:%4u)\n", inode_index, block_index, inode_offset);
|
||||
// Allocate the cache.
|
||||
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
|
||||
// Clean the cache.
|
||||
memset(cache, 0, fs->block_size);
|
||||
// Read the block containing the inode table.
|
||||
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block, cache);
|
||||
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block_index, cache);
|
||||
// Save the inode content.
|
||||
memcpy(inode, (ext2_inode_t *)((uintptr_t)cache + (offset * fs->superblock.inode_size)), fs->superblock.inode_size);
|
||||
memcpy(inode, (ext2_inode_t *)((uintptr_t)cache + (inode_offset * fs->superblock.inode_size)), sizeof(ext2_inode_t));
|
||||
// Free the cache.
|
||||
kmem_cache_free(cache);
|
||||
return 0;
|
||||
@@ -956,32 +987,35 @@ static int ext2_read_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t
|
||||
/// @return 0 on success, -1 on failure.
|
||||
static int ext2_write_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t inode_index)
|
||||
{
|
||||
uint32_t group_index, block_index, inode_offset;
|
||||
if (inode_index == 0) {
|
||||
pr_err("You are trying to read an invalid inode index (%d).\n", inode_index);
|
||||
return -1;
|
||||
}
|
||||
// Retrieve the group index.
|
||||
uint32_t group_index = ext2_get_group_index_from_inode(fs, inode_index);
|
||||
group_index = ext2_get_group_index_from_inode(fs, inode_index);
|
||||
if (group_index > fs->block_groups_count) {
|
||||
pr_err("Invalid group index computed from inode index `%d`.\n", inode_index);
|
||||
return -1;
|
||||
}
|
||||
// Get the offset of the inode inside the group.
|
||||
uint32_t offset = ext2_get_inode_offest_in_group(fs, inode_index);
|
||||
inode_offset = ext2_get_inode_offest_in_group(fs, inode_index);
|
||||
// Get the block offest.
|
||||
uint32_t block = ext2_get_block_index_from_inode_offset(fs, offset);
|
||||
block_index = ext2_get_block_index_from_inode_offset(fs, inode_offset);
|
||||
// Get the real inode offset inside the block.
|
||||
offset %= fs->inodes_per_block_count;
|
||||
inode_offset %= fs->inodes_per_block_count;
|
||||
// Log the address to the inode.
|
||||
pr_debug("Write inode (inode:%4u block:%4u offset:%4u)\n", inode_index, block_index, inode_offset);
|
||||
// Allocate the cache.
|
||||
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
|
||||
// Clean the cache.
|
||||
memset(cache, 0, fs->block_size);
|
||||
// Read the block containing the inode table.
|
||||
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block, cache);
|
||||
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block_index, cache);
|
||||
// Write the inode.
|
||||
memcpy((ext2_inode_t *)((uintptr_t)cache + (offset * fs->superblock.inode_size)), inode, fs->superblock.inode_size);
|
||||
memcpy((ext2_inode_t *)((uintptr_t)cache + (inode_offset * fs->superblock.inode_size)), inode, sizeof(ext2_inode_t));
|
||||
// Write back the block.
|
||||
ext2_write_block(fs, fs->block_groups[group_index].inode_table + block, cache);
|
||||
ext2_write_block(fs, fs->block_groups[group_index].inode_table + block_index, cache);
|
||||
// Free the cache.
|
||||
kmem_cache_free(cache);
|
||||
return 0;
|
||||
@@ -1380,6 +1414,8 @@ static ssize_t ext2_read_inode_block(ext2_filesystem_t *fs, ext2_inode_t *inode,
|
||||
uint32_t real_index = ext2_get_real_block_index(fs, inode, block_index);
|
||||
if (real_index == 0)
|
||||
return -1;
|
||||
// Log the address to the inode block.
|
||||
pr_debug("Read inode block (block:%4u real:%4u)\n", block_index, real_index);
|
||||
// Read the block.
|
||||
return ext2_read_block(fs, real_index, buffer);
|
||||
}
|
||||
@@ -1401,6 +1437,8 @@ static ssize_t ext2_write_inode_block(ext2_filesystem_t *fs, ext2_inode_t *inode
|
||||
uint32_t real_index = ext2_get_real_block_index(fs, inode, block_index);
|
||||
if (real_index == 0)
|
||||
return -1;
|
||||
// Log the address to the inode block.
|
||||
pr_debug("Write inode block (block:%4u real:%4u inode:%4u)\n", block_index, real_index, inode_index);
|
||||
// Write the block.
|
||||
return ext2_write_block(fs, real_index, buffer);
|
||||
}
|
||||
@@ -1919,7 +1957,6 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_se
|
||||
pr_err("You provided a NULL direntry.\n");
|
||||
return -1;
|
||||
}
|
||||
pr_debug("ext2_resolve_path(directory: \"%s\", path: \"%s\")\n", directory->name, path);
|
||||
// Get the filesystem.
|
||||
ext2_filesystem_t *fs = (ext2_filesystem_t *)directory->device;
|
||||
if (fs == NULL) {
|
||||
@@ -1943,8 +1980,6 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_se
|
||||
token = strtok(NULL, "/");
|
||||
}
|
||||
kfree(tmp_path);
|
||||
pr_debug("ext2_resolve_path(directory: \"%s\", path: \"%s\") -> (ino: %d, name: \"%s\")\n",
|
||||
directory->name, path, search->direntry->inode, search->direntry->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1955,7 +1990,6 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_se
|
||||
/// @return 0 on success, -1 on failure.
|
||||
static int ext2_resolve_path_direntry(vfs_file_t *directory, char *path, ext2_dirent_t *direntry)
|
||||
{
|
||||
pr_debug("ext2_resolve_path_direntry(%s, %s, %p)\n", directory->name, path, direntry);
|
||||
// Check the pointers.
|
||||
if (directory == NULL) {
|
||||
pr_err("You provided a NULL directory.\n");
|
||||
@@ -1985,7 +2019,6 @@ static int ext2_resolve_path_direntry(vfs_file_t *directory, char *path, ext2_di
|
||||
/// @return a pointer to the EXT2 filesystem, NULL otherwise.
|
||||
static ext2_filesystem_t *get_ext2_filesystem(const char *absolute_path)
|
||||
{
|
||||
pr_debug("get_ext2_filesystem(%s)\n", absolute_path);
|
||||
if (absolute_path == NULL) {
|
||||
pr_err("We received a NULL absolute path.\n");
|
||||
return NULL;
|
||||
@@ -2924,7 +2957,7 @@ static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path)
|
||||
NULL,
|
||||
NULL);
|
||||
// Compute the maximum number of inodes per block.
|
||||
fs->inodes_per_block_count = fs->block_size / sizeof(ext2_inode_t);
|
||||
fs->inodes_per_block_count = fs->block_size / fs->superblock.inode_size;
|
||||
// Compute the number of blocks per block. This value is mostly used for
|
||||
// inodes.
|
||||
// If you check inside the inode structure you will find the `blocks_count`
|
||||
|
||||
@@ -374,8 +374,6 @@ int kmain(boot_info_t *boot_informations)
|
||||
|
||||
// We have completed the booting procedure.
|
||||
pr_notice("Booting done, jumping into init process.\n");
|
||||
// Print the welcome message.
|
||||
printf("\n .: Welcome to MentOS :.\n\n");
|
||||
// Switch to the page directory of init.
|
||||
paging_switch_directory_va(init_p->mm->pgd);
|
||||
// Jump into init process.
|
||||
|
||||
@@ -300,7 +300,7 @@ static inline int __handle_signal(int signr, siginfo_t *info, sigaction_t *ka, s
|
||||
PUSH_VALUE_ON_STACK(regs->useresp, signr);
|
||||
|
||||
// Push on the stack the function required to handle the signal return.
|
||||
PUSH_VALUE_ON_STACK(regs->useresp, current->sigreturn_eip);
|
||||
PUSH_VALUE_ON_STACK(regs->useresp, current->sigreturn_addr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -631,9 +631,9 @@ int sys_kill(pid_t pid, int sig)
|
||||
return __send_sig_info(sig, &info, current);
|
||||
}
|
||||
|
||||
sighandler_t sys_signal(int signum, sighandler_t handler)
|
||||
sighandler_t sys_signal(int signum, sighandler_t handler, uint32_t sigreturn_addr)
|
||||
{
|
||||
pr_debug("sys_signal(%d, %p)\n", signum, handler);
|
||||
pr_debug("sys_signal(%d, %p, %p)\n", signum, handler, sigreturn_ptr);
|
||||
// Check the signal that we want to send.
|
||||
if ((signum < 0) || (signum >= NSIG)) {
|
||||
pr_err("sys_signal(%d, %p): Wrong signal number!\n", signum, handler);
|
||||
@@ -658,6 +658,8 @@ sighandler_t sys_signal(int signum, sighandler_t handler)
|
||||
sigemptyset(&new_sigaction.sa_mask);
|
||||
// Lock the signal handling for the given task.
|
||||
__lock_task_sighand(current);
|
||||
// Set the address of the sigreturn.
|
||||
current->sigreturn_addr = sigreturn_addr;
|
||||
// Get the old sigaction.
|
||||
sigaction_t *old_sigaction = ¤t->sighand.action[signum - 1];
|
||||
pr_err("sys_signal(%d, %p): Signal action ptr %p\n", signum, handler, old_sigaction);
|
||||
@@ -672,9 +674,9 @@ sighandler_t sys_signal(int signum, sighandler_t handler)
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
|
||||
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact, uint32_t sigreturn_addr)
|
||||
{
|
||||
pr_debug("sys_sigaction(%d, %p, %p)\n", signum, act, oldact);
|
||||
pr_debug("sys_sigaction(%d, %p, %p, %p)\n", signum, act, oldact, sigreturn_ptr);
|
||||
// Check the signal that we want to send.
|
||||
if ((signum < 0) || (signum >= NSIG)) {
|
||||
pr_err("sys_sigaction(%d, %p, %p): Wrong signal number!\n", signum, act, oldact);
|
||||
@@ -691,6 +693,8 @@ int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
|
||||
}
|
||||
// Lock the signal handling for the given task.
|
||||
__lock_task_sighand(current);
|
||||
// Set the address of the sigreturn.
|
||||
current->sigreturn_addr = sigreturn_addr;
|
||||
// Get a pointer to the entry in the sighand.action array.
|
||||
sigaction_t *current_sigaction = ¤t->sighand.action[signum - 1];
|
||||
pr_debug("sys_sigaction(%d, %p, %p): : Signal old action ptr %p\n", signum, act, oldact, current_sigaction);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/// @file ansi_colors.h
|
||||
/// @author Enrico Fraccaroli (enry.frak@gmail.com)
|
||||
/// @brief Macros for ANSI colors.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define FG_RESET "\033[0m" ///< ANSI code for resetting.
|
||||
|
||||
#define FG_BLACK "\033[30m" ///< ANSI code for setting a BLACK foreground.
|
||||
#define FG_RED "\033[31m" ///< ANSI code for setting a RED foreground.
|
||||
#define FG_GREEN "\033[32m" ///< ANSI code for setting a GREEN foreground.
|
||||
#define FG_YELLOW "\033[33m" ///< ANSI code for setting a YELLOW foreground.
|
||||
#define FG_BLUE "\033[34m" ///< ANSI code for setting a BLUE foreground.
|
||||
#define FG_MAGENTA "\033[35m" ///< ANSI code for setting a MAGENTA foreground.
|
||||
#define FG_CYAN "\033[36m" ///< ANSI code for setting a CYAN foreground.
|
||||
#define FG_WHITE "\033[37m" ///< ANSI code for setting a WHITE foreground.
|
||||
|
||||
#define FG_BLACK_BOLD "\033[1;30m" ///< ANSI code for setting a BLACK foreground.
|
||||
#define FG_RED_BOLD "\033[1;31m" ///< ANSI code for setting a RED foreground.
|
||||
#define FG_GREEN_BOLD "\033[1;32m" ///< ANSI code for setting a GREEN foreground.
|
||||
#define FG_YELLOW_BOLD "\033[1;33m" ///< ANSI code for setting a YELLOW foreground.
|
||||
#define FG_BLUE_BOLD "\033[1;34m" ///< ANSI code for setting a BLUE foreground.
|
||||
#define FG_MAGENTA_BOLD "\033[1;35m" ///< ANSI code for setting a MAGENTA foreground.
|
||||
#define FG_CYAN_BOLD "\033[1;36m" ///< ANSI code for setting a CYAN foreground.
|
||||
#define FG_WHITE_BOLD "\033[1;37m" ///< ANSI code for setting a WHITE foreground.
|
||||
|
||||
#define FG_BLACK_BRIGHT "\033[90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
|
||||
#define FG_RED_BRIGHT "\033[91m" ///< ANSI code for setting a BRIGHT_RED foreground.
|
||||
#define FG_GREEN_BRIGHT "\033[92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
|
||||
#define FG_YELLOW_BRIGHT "\033[93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
|
||||
#define FG_BLUE_BRIGHT "\033[94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
|
||||
#define FG_MAGENTA_BRIGHT "\033[95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
|
||||
#define FG_CYAN_BRIGHT "\033[96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
|
||||
#define FG_WHITE_BRIGHT "\033[97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
|
||||
|
||||
#define FG_BLACK_BRIGHT_BOLD "\033[1;90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
|
||||
#define FG_RED_BRIGHT_BOLD "\033[1;91m" ///< ANSI code for setting a BRIGHT_RED foreground.
|
||||
#define FG_GREEN_BRIGHT_BOLD "\033[1;92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
|
||||
#define FG_YELLOW_BRIGHT_BOLD "\033[1;93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
|
||||
#define FG_BLUE_BRIGHT_BOLD "\033[1;94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
|
||||
#define FG_MAGENTA_BRIGHT_BOLD "\033[1;95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
|
||||
#define FG_CYAN_BRIGHT_BOLD "\033[1;96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
|
||||
#define FG_WHITE_BRIGHT_BOLD "\033[1;97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
|
||||
|
||||
#define BG_BLACK "\033[40m" ///< ANSI code for setting a BLACK background.
|
||||
#define BG_RED "\033[41m" ///< ANSI code for setting a RED background.
|
||||
#define BG_GREEN "\033[42m" ///< ANSI code for setting a GREEN background.
|
||||
#define BG_YELLOW "\033[43m" ///< ANSI code for setting a YELLOW background.
|
||||
#define BG_BLUE "\033[44m" ///< ANSI code for setting a BLUE background.
|
||||
#define BG_MAGENTA "\033[45m" ///< ANSI code for setting a MAGENTA background.
|
||||
#define BG_CYAN "\033[46m" ///< ANSI code for setting a CYAN background.
|
||||
#define BG_WHITE "\033[47m" ///< ANSI code for setting a WHITE background.
|
||||
|
||||
#define BG_BRIGHT_BLACK "\033[100m" ///< ANSI code for setting a BRIGHT_BLACK background.
|
||||
#define BG_BRIGHT_RED "\033[101m" ///< ANSI code for setting a BRIGHT_RED background.
|
||||
#define BG_BRIGHT_GREEN "\033[102m" ///< ANSI code for setting a BRIGHT_GREEN background.
|
||||
#define BG_BRIGHT_YELLOW "\033[103m" ///< ANSI code for setting a BRIGHT_YELLOW background.
|
||||
#define BG_BRIGHT_BLUE "\033[104m" ///< ANSI code for setting a BRIGHT_BLUE background.
|
||||
#define BG_BRIGHT_MAGENTA "\033[105m" ///< ANSI code for setting a BRIGHT_MAGENTA background.
|
||||
#define BG_BRIGHT_CYAN "\033[106m" ///< ANSI code for setting a BRIGHT_CYAN background.
|
||||
#define BG_BRIGHT_WHITE "\033[107m" ///< ANSI code for setting a BRIGHT_WHITE background.
|
||||
+83
-65
@@ -3,7 +3,6 @@
|
||||
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
/// Maximum length of credentials.
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/unistd.h>
|
||||
@@ -15,50 +14,74 @@
|
||||
#include <pwd.h>
|
||||
#include <strerror.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include "ansi_colors.h"
|
||||
|
||||
/// Maximum length of credentials.
|
||||
#define CREDENTIALS_LENGTH 50
|
||||
|
||||
#define FG_BLACK "\033[30m"
|
||||
#define FG_WHITE "\033[37m"
|
||||
#define FG_RED "\033[31m"
|
||||
#define BG_WHITE "\033[47m"
|
||||
#define BG_BLACK "\033[40m"
|
||||
static inline int __setup_env(passwd_t *pwd)
|
||||
{
|
||||
// Set the USER.
|
||||
if (setenv("USER", pwd->pw_name, 1) == -1) {
|
||||
printf("Failed to set env: `USER`\n");
|
||||
return 0;
|
||||
}
|
||||
// Set the SHELL.
|
||||
if (setenv("SHELL", pwd->pw_shell, 1) == -1) {
|
||||
printf("Failed to set env: `SHELL`\n");
|
||||
return 0;
|
||||
}
|
||||
// Set the HOME.
|
||||
if (setenv("HOME", pwd->pw_dir, 1) == -1) {
|
||||
printf("Failed to set env: `HOME`\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void set_echo(bool_t active)
|
||||
static inline void __set_io_flags(unsigned flag, bool_t active)
|
||||
{
|
||||
struct termios _termios;
|
||||
tcgetattr(STDIN_FILENO, &_termios);
|
||||
if (active)
|
||||
_termios.c_lflag |= (ICANON | ECHO);
|
||||
_termios.c_lflag |= flag;
|
||||
else
|
||||
_termios.c_lflag &= ~(ICANON | ECHO);
|
||||
_termios.c_lflag &= ~flag;
|
||||
tcsetattr(STDIN_FILENO, 0, &_termios);
|
||||
}
|
||||
|
||||
void set_erase(bool_t active)
|
||||
static inline void __print_message_file(const char * file)
|
||||
{
|
||||
struct termios _termios;
|
||||
tcgetattr(STDIN_FILENO, &_termios);
|
||||
if (active)
|
||||
_termios.c_lflag |= ECHOE;
|
||||
else
|
||||
_termios.c_lflag &= ~ECHOE;
|
||||
tcsetattr(STDIN_FILENO, 0, &_termios);
|
||||
char buffer[256];
|
||||
ssize_t nbytes, total = 0;
|
||||
int fd;
|
||||
|
||||
// Try to open the file.
|
||||
if ((fd = open(file, O_RDONLY, 0600)) == -1)
|
||||
return;
|
||||
// Read the lines of the file.
|
||||
while ((nbytes = read(fd, buffer, sizeof(char) * 256)) > 0) {
|
||||
// TODO: Parsing message files for special characters (such as `\t` for time).
|
||||
printf("%s\n", buffer);
|
||||
total += nbytes;
|
||||
}
|
||||
close(fd);
|
||||
if (total > 0)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/// @brief Gets the inserted command.
|
||||
static bool_t get_input(char *input, size_t max_len, bool_t hide)
|
||||
static inline bool_t __get_input(char *input, size_t max_len, bool_t hide)
|
||||
{
|
||||
size_t index = 0;
|
||||
int c;
|
||||
bool_t result = false;
|
||||
|
||||
//set_erase(false);
|
||||
if (hide) {
|
||||
set_echo(false);
|
||||
}
|
||||
__set_io_flags(ICANON, false);
|
||||
if (hide)
|
||||
__set_io_flags(ECHO, false);
|
||||
|
||||
memset(input, 0, max_len);
|
||||
do {
|
||||
@@ -104,6 +127,8 @@ static bool_t get_input(char *input, size_t max_len, bool_t hide)
|
||||
putchar('\b');
|
||||
--index;
|
||||
}
|
||||
} else if (c == 0) {
|
||||
// Do nothing.
|
||||
} else {
|
||||
input[index++] = c;
|
||||
if (index == (max_len - 1)) {
|
||||
@@ -114,59 +139,34 @@ static bool_t get_input(char *input, size_t max_len, bool_t hide)
|
||||
}
|
||||
} while (index < max_len);
|
||||
|
||||
//set_erase(true);
|
||||
if (hide) {
|
||||
set_echo(true);
|
||||
__set_io_flags(ECHO, true);
|
||||
putchar('\n');
|
||||
}
|
||||
__set_io_flags(ICANON, true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int setup_env(passwd_t *pwd)
|
||||
{
|
||||
// Set the USER.
|
||||
if (setenv("USER", pwd->pw_name, 1) == -1) {
|
||||
printf("Failed to set env: `USER`\n");
|
||||
return 0;
|
||||
}
|
||||
// Set the SHELL.
|
||||
if (setenv("SHELL", pwd->pw_shell, 1) == -1) {
|
||||
printf("Failed to set env: `SHELL`\n");
|
||||
return 0;
|
||||
}
|
||||
// Set the HOME.
|
||||
if (setenv("HOME", pwd->pw_dir, 1) == -1) {
|
||||
printf("Failed to set env: `HOME`\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Print /etc/issue if it exists
|
||||
// TODO: Parsing /etc/issue for special characters (such as `\t` for time)
|
||||
int issues_fd = open("/etc/issue", O_RDONLY, 0600);
|
||||
if (issues_fd != -1){
|
||||
char buffer[256];
|
||||
|
||||
if(read(issues_fd, buffer, sizeof(char)*256) != -1){
|
||||
printf("%s \n", buffer);
|
||||
}
|
||||
close(issues_fd);
|
||||
}
|
||||
|
||||
// Print /etc/issue if it exists.
|
||||
__print_message_file("/etc/issue");
|
||||
|
||||
passwd_t *pwd;
|
||||
char username[50], password[50];
|
||||
char username[CREDENTIALS_LENGTH], password[CREDENTIALS_LENGTH];
|
||||
do {
|
||||
// Get the username.
|
||||
do {
|
||||
printf("Username :");
|
||||
} while (!get_input(username, 50, false));
|
||||
} while (!__get_input(username, CREDENTIALS_LENGTH, false));
|
||||
|
||||
// Get the password.
|
||||
do {
|
||||
printf("Password :");
|
||||
} while (!get_input(password, 50, true));
|
||||
} while (!__get_input(password, CREDENTIALS_LENGTH, true));
|
||||
|
||||
// Check if we can find the user.
|
||||
if ((pwd = getpwnam(username)) == NULL) {
|
||||
if (errno == ENOENT) {
|
||||
printf("The given name was not found.\n");
|
||||
@@ -177,29 +177,47 @@ int main(int argc, char **argv)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the password is correct.
|
||||
if (strcmp(pwd->pw_passwd, password) != 0) {
|
||||
printf("Wrong password.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
// If there is not shell set for the user, should we rollback to standard shell?
|
||||
if (pwd->pw_shell == NULL) {
|
||||
printf("%s: There is no shell set for the user `%s`.\n", argv[0], pwd->pw_name);
|
||||
printf("login: There is no shell set for the user `%s`.\n", pwd->pw_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!setup_env(pwd)) {
|
||||
printf("%s: Failed to setup the environmental variables.\n", argv[0]);
|
||||
// Set the standard environmental variables.
|
||||
if (!__setup_env(pwd)) {
|
||||
printf("login: Failed to setup the environmental variables.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set the group id.
|
||||
setgid(pwd->pw_gid);
|
||||
|
||||
// Set the user id.
|
||||
setuid(pwd->pw_uid);
|
||||
|
||||
// Print /etc/motd if it exists.
|
||||
__print_message_file("/etc/motd");
|
||||
|
||||
// Welcome the user.
|
||||
puts(BG_WHITE FG_BLACK);
|
||||
printf("Welcome " FG_RED "%s" FG_BLACK "...\n", pwd->pw_name);
|
||||
puts(BG_BLACK FG_WHITE_BRIGHT);
|
||||
|
||||
// Call the shell.
|
||||
char *_argv[] = { pwd->pw_shell, (char *)NULL };
|
||||
if (execv(pwd->pw_shell, _argv) == -1) {
|
||||
printf("%s: Failed to execute the shell.\n", argv[0]);
|
||||
printf("%s: %s.\n", argv[0], strerror(errno));
|
||||
printf("login: Failed to execute the shell.\n");
|
||||
printf("login: %s.\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
+54
-19
@@ -3,32 +3,67 @@
|
||||
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include <strerror.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <strerror.h>
|
||||
#include <string.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd = open("/bin", O_RDONLY | O_DIRECTORY, 0);
|
||||
if (fd == -1) {
|
||||
printf("%s: cannot access '/bin': %s\n\n", argv[0], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
dirent_t dent;
|
||||
int per_line = 0;
|
||||
while (getdents(fd, &dent, sizeof(dirent_t)) == sizeof(dirent_t)) {
|
||||
// Shows only regular files
|
||||
if(dent.d_type == DT_REG){
|
||||
printf("%10s ", dent.d_name);
|
||||
if (++per_line == 6) {
|
||||
per_line = 0;
|
||||
putchar('\n');
|
||||
if (argc == 1)
|
||||
{
|
||||
int fd = open("/bin", O_RDONLY | O_DIRECTORY, 0);
|
||||
if (fd == -1)
|
||||
{
|
||||
printf("%s: cannot access '/bin': %s\n\n", argv[0], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
dirent_t dent;
|
||||
int per_line = 0;
|
||||
while (getdents(fd, &dent, sizeof(dirent_t)) == sizeof(dirent_t))
|
||||
{
|
||||
// Shows only regular files
|
||||
if (dent.d_type == DT_REG)
|
||||
{
|
||||
printf("%10s ", dent.d_name);
|
||||
if (++per_line == 6)
|
||||
{
|
||||
per_line = 0;
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
close(fd);
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
char filepath[PATH_MAX];
|
||||
strcpy(filepath, "/usr/share/man/");
|
||||
strcat(filepath, argv[1]);
|
||||
strcat(filepath, ".man");
|
||||
int fd = open(filepath, O_RDONLY, 42);
|
||||
if (fd < 0)
|
||||
{
|
||||
printf("%s: No manual entry for %s\n\n", argv[0], argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prepare the buffer for reading the man file.
|
||||
char buffer[BUFSIZ];
|
||||
// Put on the standard output the characters.
|
||||
while (read(fd, buffer, BUFSIZ) > 0)
|
||||
{
|
||||
puts(buffer);
|
||||
}
|
||||
// Close the file descriptor.
|
||||
close(fd);
|
||||
// Terminate with a pair of newlines.
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+2
-52
@@ -21,46 +21,13 @@
|
||||
#include "limits.h"
|
||||
#include "sys/utsname.h"
|
||||
#include "ctype.h"
|
||||
#include "ansi_colors.h"
|
||||
|
||||
/// Maximum length of commands.
|
||||
#define CMD_LEN 32
|
||||
/// Maximum lenght of the history.
|
||||
#define HISTORY_MAX 10
|
||||
|
||||
/// @brief A set of colors.
|
||||
#define FG_BLACK "\033[30m"
|
||||
#define FG_RED "\033[31m"
|
||||
#define FG_GREEN "\033[32m"
|
||||
#define FG_YELLOW "\033[33m"
|
||||
#define FG_BLUE "\033[34m"
|
||||
#define FG_MAGENTA "\033[35m"
|
||||
#define FG_CYAN "\033[36m"
|
||||
#define FG_WHITE "\033[37m"
|
||||
#define FG_BRIGHT_BLACK "\033[90m"
|
||||
#define FG_BRIGHT_RED "\033[91m"
|
||||
#define FG_BRIGHT_GREEN "\033[92m"
|
||||
#define FG_BRIGHT_YELLOW "\033[93m"
|
||||
#define FG_BRIGHT_BLUE "\033[94m"
|
||||
#define FG_BRIGHT_MAGENTA "\033[95m"
|
||||
#define FG_BRIGHT_CYAN "\033[96m"
|
||||
#define FG_BRIGHT_WHITE "\033[97m"
|
||||
#define BG_BLACK "\033[40m"
|
||||
#define BG_RED "\033[41m"
|
||||
#define BG_GREEN "\033[42m"
|
||||
#define BG_YELLOW "\033[43m"
|
||||
#define BG_BLUE "\033[44m"
|
||||
#define BG_MAGENTA "\033[45m"
|
||||
#define BG_CYAN "\033[46m"
|
||||
#define BG_WHITE "\033[47m"
|
||||
#define BG_BRIGHT_BLACK "\033[100m"
|
||||
#define BG_BRIGHT_RED "\033[101m"
|
||||
#define BG_BRIGHT_GREEN "\033[102m"
|
||||
#define BG_BRIGHT_YELLOW "\033[103m"
|
||||
#define BG_BRIGHT_BLUE "\033[104m"
|
||||
#define BG_BRIGHT_MAGENTA "\033[105m"
|
||||
#define BG_BRIGHT_CYAN "\033[106m"
|
||||
#define BG_BRIGHT_WHITE "\033[107m"
|
||||
|
||||
// Required by `export`
|
||||
#define ENV_NORM 1
|
||||
#define ENV_BRAK 2
|
||||
@@ -188,7 +155,7 @@ static inline void __prompt_print()
|
||||
} else {
|
||||
HOSTNAME = buffer.nodename;
|
||||
}
|
||||
printf(FG_GREEN "%s" FG_WHITE "@" FG_CYAN "%s " FG_BRIGHT_BLUE "[%02d:%02d:%02d]" FG_WHITE " [%s] " FG_BRIGHT_WHITE "%% ",
|
||||
printf(FG_GREEN "%s" FG_WHITE "@" FG_CYAN "%s " FG_BLUE_BRIGHT "[%02d:%02d:%02d]" FG_WHITE " [%s] " FG_WHITE_BRIGHT "%% ",
|
||||
USER, HOSTNAME, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, CWD);
|
||||
}
|
||||
|
||||
@@ -704,23 +671,6 @@ int main(int argc, char *argv[])
|
||||
printf("Failed to set signal handler (%s).\n", SIGCHLD, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
// Clear the screen.
|
||||
puts("\033[J");
|
||||
// Welcome the user.
|
||||
puts(BG_WHITE FG_BLACK);
|
||||
printf("Welcome " FG_RED "%s" FG_BLACK "...\n\n", USER);
|
||||
puts(BG_BLACK FG_BRIGHT_WHITE);
|
||||
|
||||
// Print /etc/motd if it exists
|
||||
int motd_fd = open("/etc/motd", O_RDONLY, 0600);
|
||||
if (motd_fd != -1){
|
||||
char buffer[256];
|
||||
|
||||
if(read(motd_fd, buffer, sizeof(char)*256) != -1){
|
||||
printf("%s \n", buffer);
|
||||
}
|
||||
close(motd_fd);
|
||||
}
|
||||
|
||||
// Move inside the home directory.
|
||||
__cd(0, NULL);
|
||||
|
||||
Reference in New Issue
Block a user