shell and ls command

This commit is contained in:
Guamss 2026-04-27 16:46:30 +02:00
parent ba12753402
commit a43436b20b
12 changed files with 203 additions and 75 deletions

View File

@ -1,7 +1,7 @@
NAME := seyshell NAME := seyshell
DRIVE := disk DRIVE := disk
CC := gcc CC := gcc
CFLAGS := CFLAGS := -Wall -Wextra -Werror -g
OBJ_DIR := obj OBJ_DIR := obj
SRC_DIR := src SRC_DIR := src

View File

@ -7,6 +7,5 @@
#define TYPE_NULL 0 #define TYPE_NULL 0
#define TYPE_FILE 1 #define TYPE_FILE 1
#define TYPE_BINARY 2
#define TYPE_DIRECTORY 3 #define TYPE_DIRECTORY 3
#define TYPE_SYMBOLIC_LINK 4 #define TYPE_SYMBOLIC_LINK 4

View File

@ -1,5 +1,6 @@
/** @file */ /** @file */
#include "disk.h" #include "disk.h"
#include "env.h"
#include "struct.h" #include "struct.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -48,15 +49,12 @@ int find_offset_in_parent_bloc(bloc *parent_bloc) {
return -1; return -1;
} }
int create_directory(disk *disk, inode *parent, char *dirname) {} int allocate_node(disk *disk, inode *parent, char *name, char type) {
int create_file(disk *disk, inode *parent, char *filename) {
int inode_index = 0; int inode_index = 0;
while (inode_index < MAX_INODE && while (inode_index < MAX_INODE &&
disk->inodes[inode_index].filetype != TYPE_NULL) { disk->inodes[inode_index].filetype != TYPE_NULL) {
inode_index++; inode_index++;
} }
if (inode_index >= MAX_INODE) { if (inode_index >= MAX_INODE) {
dprintf(STDERR_FILENO, "No free inodes\n"); dprintf(STDERR_FILENO, "No free inodes\n");
return -1; return -1;
@ -70,46 +68,42 @@ int create_file(disk *disk, inode *parent, char *filename) {
int p_bloc_idx = parent->blocs[0]; int p_bloc_idx = parent->blocs[0];
int offset = find_offset_in_parent_bloc(&disk->blocs[p_bloc_idx]); int offset = find_offset_in_parent_bloc(&disk->blocs[p_bloc_idx]);
if (offset == -1) { if (offset == -1) {
dprintf(STDERR_FILENO, "Parent directory full\n"); dprintf(STDERR_FILENO, "Parent directory full\n");
return -1; return -1;
} }
strncpy(&disk->blocs[p_bloc_idx].datas[offset], filename, MAX_INODE_NAME); strncpy(&disk->blocs[p_bloc_idx].datas[offset], name, MAX_INODE_NAME);
memcpy(&disk->blocs[p_bloc_idx].datas[offset + MAX_INODE_NAME], &inode_index, memcpy(&disk->blocs[p_bloc_idx].datas[offset + MAX_INODE_NAME], &inode_index,
sizeof(int)); sizeof(int));
init_inode_in_disk(disk, inode_index, TYPE_FILE, 0b111111111, new_bloc_idx); init_inode_in_disk(disk, inode_index, type, 0b111111111, new_bloc_idx);
return inode_index; return inode_index;
} }
int create_inode(disk *disk, inode *parent, char inode_type, char *name) { int create_file(disk *disk, inode *parent, char *filename) {
if (strlen(name) > MAX_INODE_NAME) { return allocate_node(disk, parent, filename, TYPE_FILE);
dprintf(STDERR_FILENO, "A inode name must be < %d\n", MAX_INODE_NAME); }
return -1;
}
if (parent->filetype != TYPE_DIRECTORY) {
dprintf(STDERR_FILENO, "A parent's inode must be a directory!\n");
return -1;
}
switch (inode_type) { int create_directory(disk *disk, inode *parent, char *dirname) {
case TYPE_DIRECTORY: int new_idx = allocate_node(disk, parent, dirname, TYPE_DIRECTORY);
return create_directory(disk, parent, name);
break; if (new_idx == -1)
case TYPE_FILE: return -1;
return create_file(disk, parent, name);
case TYPE_BINARY: int bloc_idx = disk->inodes[new_idx].blocs[0];
// TODO plus tard int entry_size = MAX_INODE_NAME + sizeof(int);
break; int p_idx = (int)(parent - disk->inodes);
case TYPE_SYMBOLIC_LINK:
// TODO plus tard strncpy(&disk->blocs[bloc_idx].datas[0], ".", MAX_INODE_NAME);
break; memcpy(&disk->blocs[bloc_idx].datas[MAX_INODE_NAME], &new_idx, sizeof(int));
default:
break; strncpy(&disk->blocs[bloc_idx].datas[entry_size], "..", MAX_INODE_NAME);
} memcpy(&disk->blocs[bloc_idx].datas[entry_size + MAX_INODE_NAME], &p_idx,
return -1; sizeof(int));
return new_idx;
} }
void write_in_file(disk *d, int file_index, char *data /*, char mode*/) { void write_in_file(disk *d, int file_index, char *data /*, char mode*/) {
@ -133,15 +127,60 @@ void write_in_file(disk *d, int file_index, char *data /*, char mode*/) {
strncpy(&d->blocs[bloc_index_to_overwrite].datas[0], data, strlen(data)); strncpy(&d->blocs[bloc_index_to_overwrite].datas[0], data, strlen(data));
} }
void do_ls(disk *d, int dir_index) { int find_dir_inode_by_name(char *name, int dir_index, disk *d) {
inode dir = d->inodes[dir_index];
if (dir.filetype != TYPE_DIRECTORY) { int bloc = d->inodes[dir_index].blocs[0];
dprintf(STDERR_FILENO, "ls: Can only list in directories\n");
return; for (int i = 0; i < MAX_BYTES_PER_BLOC; i += MAX_INODE_NAME + sizeof(int)) {
char inode_name[MAX_INODE_NAME];
strncpy(inode_name, &d->blocs[bloc].datas[i], MAX_INODE_NAME);
if (strcmp(name, inode_name) == 0) {
int inode_id;
memcpy(&inode_id, &d->blocs[bloc].datas[i + MAX_INODE_NAME], sizeof(int));
return inode_id;
}
} }
// TODO: chercher sur tous les blocs possédés return -1;
int bloc = dir.blocs[0]; }
int do_ls(disk *d, char *path) {
char *path_to_process;
if (path == NULL) {
path_to_process = strdup(get_env_value("PWD"));
} else {
path_to_process = strdup(path);
}
int dir_index = 0;
char *token = strtok(path_to_process, "/");
while (token != NULL) {
dir_index = find_dir_inode_by_name(token, dir_index, d);
if (dir_index == -1) {
dprintf(STDERR_FILENO, "ls: This directory does not exist\n");
free(path_to_process);
return -1;
}
if (d->inodes[dir_index].filetype != TYPE_DIRECTORY) {
dprintf(STDERR_FILENO, "ls: '%s' is not a directory\n", token);
free(path_to_process);
return -1;
}
token = strtok(NULL, "/");
}
inode dir_to_list = d->inodes[dir_index];
int bloc = dir_to_list.blocs[0];
if (bloc == -1) {
free(path_to_process);
return 1;
}
for (int i = 0; i < MAX_BYTES_PER_BLOC; i += MAX_INODE_NAME + sizeof(int)) { for (int i = 0; i < MAX_BYTES_PER_BLOC; i += MAX_INODE_NAME + sizeof(int)) {
if (d->blocs[bloc].datas[i] != '\0') { if (d->blocs[bloc].datas[i] != '\0') {
@ -150,6 +189,9 @@ void do_ls(disk *d, int dir_index) {
dprintf(STDOUT_FILENO, "%-16s %d\n", &d->blocs[bloc].datas[i], inode_id); dprintf(STDOUT_FILENO, "%-16s %d\n", &d->blocs[bloc].datas[i], inode_id);
} }
} }
free(path_to_process);
return 1;
} }
char *read_in_file(disk *d, int file_index) { char *read_in_file(disk *d, int file_index) {
@ -163,7 +205,8 @@ char *read_in_file(disk *d, int file_index) {
int bloc = file.blocs[0]; int bloc = file.blocs[0];
char *out; char *out;
int c_index = 0; int c_index = 0;
while (d->blocs[bloc].datas[c_index] != '\0' || c_index < MAX_BYTES_PER_BLOC) { while (d->blocs[bloc].datas[c_index] != '\0' ||
c_index < MAX_BYTES_PER_BLOC) {
c_index++; c_index++;
} }
@ -178,9 +221,11 @@ char *read_in_file(disk *d, int file_index) {
return out; return out;
} }
void init_env_var_file(disk *d) { void init_test_files(disk *d) {
int inode_idx = create_inode(d, &d->inodes[0], TYPE_FILE, "env"); int inode_idx = create_file(d, &d->inodes[0], "test");
write_in_file(d, inode_idx, "PWD=/\nUSER=user"); write_in_file(d, inode_idx, "Contenu du fichier :)\n");
int dir_idx = create_directory(d, &d->inodes[0], "dir");
create_file(d, &d->inodes[dir_idx], "test1");
} }
/** /**
@ -211,7 +256,7 @@ disk create_disk() {
d.inodes[0].blocs[0] = 0; // utilise le bloc 0 d.inodes[0].blocs[0] = 0; // utilise le bloc 0
d.owned_blocs[0] = 1; // le bloc 1 est maintenant occupé d.owned_blocs[0] = 1; // le bloc 1 est maintenant occupé
init_env_var_file(&d); init_test_files(&d);
int n = fwrite(&d, sizeof(disk), 1, fptr); int n = fwrite(&d, sizeof(disk), 1, fptr);
if (n == 1) { if (n == 1) {

View File

@ -5,7 +5,8 @@
#include "const.h" #include "const.h"
#include "struct.h" #include "struct.h"
#include <string.h> #include <string.h>
#include "env.h"
disk create_disk(); disk create_disk();
disk open_disk(char* filename); disk open_disk(char* filename);
void do_ls(disk *d, int dir_index); int do_ls(disk *d, char* path);

47
src/env.c Normal file
View File

@ -0,0 +1,47 @@
#include "env.h"
env *init_envs() {
env *envs = malloc(sizeof(env) * 3);
if (envs == NULL)
return NULL;
envs[0].key = "PWD";
envs[0].value = "/";
envs[1].key = "USER";
envs[1].value = "guams";
envs[2].key = "HOST";
envs[2].value = "tartempion";
return envs;
}
env *get_instance() {
static env *instance = NULL;
if (instance == NULL) {
instance = init_envs();
}
return instance;
}
int get_env_len(env *envs) {
int i = 0;
while (envs[i].key != NULL) {
i++;
}
return i;
}
char *get_env_value(char *key) {
env *envs = get_instance();
for (int i = 0; i < get_env_len(envs); i++) {
if (strcmp(envs[i].key, key) == 0) {
return envs[i].value;
}
}
return NULL;
}

8
src/env.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "struct.h"
#include <stdlib.h>
#include <string.h>
char* get_env_value(char* key);
int get_env_len(env *envs);
env* init_envs();

View File

@ -1,18 +1,13 @@
/** @file */ /** @file */
#include "exec.h" #include "exec.h"
#include "disk.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
// TODO : Tout ce fichier est à changer je pense
int is_builtin_cmd(char *executable) {
(void)executable;
return 0;
}
// à changer parce que je veux pas chercher dans le PATH, je veux juste executer // à changer parce que je veux pas chercher dans le PATH, je veux juste executer
// les futures primitives qui seront implémentées // les futures primitives qui seront implémentées
int execute_cmd(char **args) { /*int execute_cmd(char **args) {
if (!is_builtin_cmd(args[0])) { if (!is_builtin_cmd(args[0])) {
int pid = fork(); int pid = fork();
if (pid == -1) if (pid == -1)
@ -31,3 +26,27 @@ int execute_cmd(char **args) {
} }
return 1; return 1;
} }
*/
int child_process_job(disk *d, char **args) {
if (strcmp("ls", args[0]) == 0) {
do_ls(d, args[1]);
}
return 1;
}
int execute_cmd(disk *d, char **args) {
int pid = fork();
if (pid == 1) {
return -1;
}
if (pid == 0) {
child_process_job(d, args);
} else {
int status;
waitpid(pid, &status, WUNTRACED);
}
return 1;
}

View File

@ -1,7 +1,8 @@
/** @file */ /** @file */
#pragma once #pragma once
#include "disk.h"
#include <stdio.h> #include <stdio.h>
#include <sys/wait.h> #include <sys/wait.h>
int is_builtin_cmd(char *executable); int is_builtin_cmd(char *executable);
int execute_cmd(char **args); int execute_cmd(disk *d, char **args);

View File

@ -1,24 +1,17 @@
/** @file */ /** @file */
#include "disk.h" #include "disk.h"
#include "parsing.h" #include "parsing.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int main(int argc, char *argv[], char *envp[]) { int main() {
(void)argc;
(void)argv;
(void)envp;
// shell_loop();
disk drive; disk drive;
if (access("disk", F_OK) == 0) { if (access("disk", F_OK) == 0) {
drive = open_disk("disk"); drive = open_disk("disk");
do_ls(&drive, 0);
} else } else
drive = create_disk(); drive = create_disk();
(void)drive; open_seyshell(&drive);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -1,6 +1,7 @@
/** @file */ /** @file */
#include "parsing.h" #include "parsing.h"
#include "const.h" #include "const.h"
#include "env.h"
#include "exec.h" #include "exec.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -15,6 +16,8 @@
char *read_line() { char *read_line() {
char c; char c;
int i = 0; int i = 0;
// buffer overflow attention
char *buffer = malloc(BUFSIZE * sizeof(char)); char *buffer = malloc(BUFSIZE * sizeof(char));
if (buffer == NULL) { if (buffer == NULL) {
dprintf(STDERR_FILENO, "Line read buffer allocation error !"); dprintf(STDERR_FILENO, "Line read buffer allocation error !");
@ -70,15 +73,14 @@ char **split_line(char *line) {
* @see char** split_line(char *line) * @see char** split_line(char *line)
* @see int execute_cmd(char **args) * @see int execute_cmd(char **args)
*/ */
void shell_loop(void) { void shell_loop(disk *disk) {
char *user = getenv("USER"); char *user = get_env_value("USER");
char *hostname = malloc(BUFSIZE * sizeof(char)); if (user == NULL) {
if (hostname == NULL) { exit(EXIT_FAILURE);
dprintf(STDERR_FILENO, "Allocation error");
} }
// sur le sgf le hostname se récupèrera pas comme ça donc à changer :)
gethostname(hostname, sizeof(hostname)); char *hostname = get_env_value("HOST");
char *line; char *line;
char **args; char **args;
@ -86,13 +88,19 @@ void shell_loop(void) {
do { do {
// ça aussi c'est pas bien, ça sera à changer une fois le sgf fonctionnel // ça aussi c'est pas bien, ça sera à changer une fois le sgf fonctionnel
dprintf(STDOUT_FILENO, "%s@%s %s> ", user, hostname, getenv("PWD")); dprintf(STDOUT_FILENO, "%s@%s %s> ", user, hostname, get_env_value("PWD"));
line = read_line(); line = read_line();
args = split_line(line); args = split_line(line);
status = execute_cmd(args); status = execute_cmd(disk, args);
free(line); free(line);
free(args); free(args);
} while (status); } while (status);
} }
void open_seyshell(disk* disk) {
env* envs = init_envs();
shell_loop(disk);
free(envs);
}

View File

@ -1,7 +1,9 @@
/** @file */ /** @file */
#pragma once #pragma once
#include "env.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "struct.h"
void shell_loop(void); void open_seyshell(disk* disk);

View File

@ -2,6 +2,11 @@
#pragma once #pragma once
#include "const.h" #include "const.h"
typedef struct env {
char* key;
char* value;
} env;
/** /**
* @struct inode * @struct inode
* @brief Un inode est un fichier, il possède des permissions, un type * @brief Un inode est un fichier, il possède des permissions, un type