i have make os_error_handler
its has 4 files
src
logs
dashboard
Makefile

in src we have error_handler.c , error_handler.h, logger.c , logger.h, recovery.c, recovery.h, reporter.c, reporter.h
and one folder named "simulations" that has simulate_device_error.c, simulate_file_error.c, simulate_memory_error.c

in logs we have error_log.log

in dashboard we have app.py and template folder that has index.html and stats.html

I will provide the content inside it, i just want to know how to run this project

// File: src/error_handler.c
#include "error_handler.h"
#include "logger.h"
#include "reporter.h"
#include "recovery.h"
#include <stdio.h>
#include <stdlib.h>

// Function implementation
void handle_error(ErrorType type, const char *message, int error_code) {
// Log the error
log_error(type, message, error_code);

code
// Report the error
report_error(type, message, error_code);

// Attempt recovery
recover_from_error(type);
}

// File: src/error_handler.h
#ifndef ERROR_HANDLER_H
#define ERROR_HANDLER_H

typedef enum {
MEMORY_ERROR,
FILE_ACCESS_ERROR,
DEVICE_ERROR,
NULL_ERROR, // Added NULL_ERROR for null pointer dereference
UNKNOWN_ERROR
} ErrorType;

// Function to handle errors
void handle_error(ErrorType type, const char *message, int error_code);

#endif // ERROR_HANDLER_H

// File: src/logger.c
#include "logger.h"
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <sys/stat.h>

#define LOG_FILE "logs/error_log.log"
#define MAX_LOG_SIZE 5242880 // 5MB

pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;

// Function to get current timestamp
const char* current_timestamp() {
static char buffer[20];
time_t now = time(NULL);
struct tm *t = localtime(&now);
strftime(buffer, sizeof(buffer)-1, "%Y-%m-%d %H:%M:%S", t);
return buffer;
}

// Function to convert ErrorType to string
const char* error_type_to_string(ErrorType type) {
switch(type) {
case MEMORY_ERROR:
return "MEMORY_ERROR";
case FILE_ACCESS_ERROR:
return "FILE_ACCESS_ERROR";
case DEVICE_ERROR:
return "DEVICE_ERROR";
default:
return "UNKNOWN_ERROR";
}
}

// Function to rotate logs if needed
void rotate_logs_if_needed() {
struct stat st;
if (stat(LOG_FILE, &st) == 0) {
if (st.st_size >= MAX_LOG_SIZE) {
// Rename the current log file with a timestamp
char new_name[256];
time_t now = time(NULL);
struct tm *t = localtime(&now);
strftime(new_name, sizeof(new_name), "logs/error_log_%Y%m%d%H%M%S.log", t);
rename(LOG_FILE, new_name);
}
}
}

void log_error(ErrorType type, const char *message, int error_code) {
pthread_mutex_lock(&log_mutex);
rotate_logs_if_needed();
FILE *file = fopen(LOG_FILE, "a");
if (!file) {
pthread_mutex_unlock(&log_mutex);
return;
}

code
fprintf(file, "[%s] %s: %s (Error Code: %d)\n", current_timestamp(), error_type_to_string(type), message, error_code);
fclose(file);
pthread_mutex_unlock(&log_mutex);
}

// File: src/logger.h
#ifndef LOGGER_H
#define LOGGER_H

#include "error_handler.h"

void log_error(ErrorType type, const char *message, int error_code);

#endif // LOGGER_H

// File: src/recovery.c
#include "recovery.h"
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// Define maximum retries and delay
#define MAX_RETRIES 3
#define RETRY_DELAY 2 // seconds

void recover_from_file_access_error(const char *filepath) {
for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
printf("Retrying file access (Attempt %d)...\n", attempt);
FILE *file = fopen(filepath, "r");
if (file != NULL) {
printf("File accessed successfully on attempt %d.\n", attempt);
fclose(file);
return;
}
sleep(RETRY_DELAY);
}
printf("Failed to recover from FILE_ACCESS_ERROR after %d attempts.\n", MAX_RETRIES);
// Further actions, like using fallback
}

void recover_from_error(ErrorType type) {
switch(type) {
case MEMORY_ERROR:
printf("Attempting to recover from MEMORY_ERROR...\n");
// Implement recovery logic, e.g., free memory, restart process
// For demonstration, we'll simply exit
exit(EXIT_FAILURE);
break;
case FILE_ACCESS_ERROR:
printf("Attempting to recover from FILE_ACCESS_ERROR...\n");
// Example: Retry file access
recover_from_file_access_error("/path/to/nonexistent/file.txt");
break;
case DEVICE_ERROR:
printf("Attempting to recover from DEVICE_ERROR...\n");
// Attempt to reinitialize the device or switch to a backup
// For demonstration, we'll log and continue
break;
default:
printf("Unknown error type. Unable to recover.\n");
exit(EXIT_FAILURE);
}
}

// File: src/recovery.h
#ifndef RECOVERY_H
#define RECOVERY_H

#include "error_handler.h"

void recover_from_error(ErrorType type);

#endif // RECOVERY_H

// File: src/reporter.c
#include "reporter.h"
#include <stdio.h>
#include <string.h>

// Define recipient and sender email
#define RECIPIENT_EMAIL "b22cs004@iitj.ac.in"
#define SENDER_EMAIL "advaitgaur2003@gmail.com"

// Function to send email using sendmail
void send_email(const char *subject, const char *body) {
FILE *mail = popen("/usr/sbin/sendmail -t", "w");
if (mail == NULL) {
// Failed to open sendmail
return;
}

code
fprintf(mail, "To: %s\n", RECIPIENT_EMAIL);
fprintf(mail, "From: %s\n", SENDER_EMAIL);
fprintf(mail, "Subject: %s\n\n", subject);
fprintf(mail, "%s\n", body);

pclose(mail);
}

void report_error(ErrorType type, const char *message, int error_code) {
char subject[256];
char body[1024];

code
// Convert ErrorType to string
const char *type_str;
switch(type) {
case MEMORY_ERROR:
type_str = "MEMORY_ERROR";
break;
case FILE_ACCESS_ERROR:
type_str = "FILE_ACCESS_ERROR";
break;
case DEVICE_ERROR:
type_str = "DEVICE_ERROR";
break;
default:
type_str = "UNKNOWN_ERROR";
}

snprintf(subject, sizeof(subject), "OS Error Report: %s", type_str);
snprintf(body, sizeof(body), "An error of type %s occurred.\nDetails: %s\nError Code: %d",
type_str, message, error_code);

send_email(subject, body);
}

// File: src/reporter.h
#ifndef REPORTER_H
#define REPORTER_H

#include "error_handler.h"

void report_error(ErrorType type, const char *message, int error_code);

#endif // REPORTER_H

// File: src/simulations/simulate_device_error.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "error_handler.h"

int main() {
printf("Simulating device access error...\n");
int fd = open("/dev/nonexistent_device", O_RDONLY);
if (fd == -1) {
printf("Device Error: %s\n", strerror(errno));
handle_error(DEVICE_ERROR, strerror(errno), errno);
return errno;
}
close(fd);
return 0;
}

// File: src/simulations/simulate_file_error.c
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "error_handler.h"

int main() {
printf("Simulating file access error...\n");
FILE *file = fopen("/path/to/nonexistent/file.txt", "r");
if (file == NULL) {
printf("File Access Error: %s\n", strerror(errno));
handle_error(FILE_ACCESS_ERROR, strerror(errno), errno);
return errno;
}
fclose(file);
return 0;
}

// File: src/simulations/simulate_memory_error.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error_handler.h"

// Function to simulate a memory leak
void simulate_memory_leak() {
printf("Simulating memory leak...\n");
while (1) {
malloc(1024 * 1024); // Allocate 1MB without freeing
sleep(1);
}
}

// Function to simulate a segmentation fault
void simulate_segmentation_fault() {
printf("Simulating segmentation fault...\n");
int *ptr = NULL;
*ptr = 42; // Dereference NULL pointer
}

// Function to simulate a null pointer dereference
void simulate_null_pointer_deref() {
printf("Simulating null pointer dereference...\n");
int *ptr = NULL;
if (ptr) {
*ptr = 100;
} else {
printf("Attempted to dereference a null pointer.\n");
handle_error(NULL_ERROR, "Null pointer dereference detected.", 0);
}
}

int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: %s <leak|segfault|null>\n", argv[0]);
return 1;
}

code
if (strcmp(argv[1], "leak") == 0) {
simulate_memory_leak();
} else if (strcmp(argv[1], "segfault") == 0) {
simulate_segmentation_fault();
} else if (strcmp(argv[1], "null") == 0) {
simulate_null_pointer_deref();
} else {
printf("Unknown simulation type.\n");
return 1;
}

return 0;
}

File: dashboard/app.py
from flask import Flask, render_template
import collections
import os

app = Flask(name)

LOG_FILE = os.path.join(os.path.dirname(os.path.abspath(file)), '../logs/error_log.log')

def read_logs():
try:
with open(LOG_FILE, 'r') as file:
return file.readlines()
except FileNotFoundError:
return []

@app.route('/')
def index():
logs = read_logs()[-100:] # Display the last 100 log entries
return render_template('index.html', logs=logs)

@app.route('/stats')
def stats():
stats_counter = collections.Counter()
logs = read_logs()
for line in logs:
if "MEMORY_ERROR" in line:
stats_counter['MEMORY_ERROR'] += 1
elif "FILE_ACCESS_ERROR" in line:
stats_counter['FILE_ACCESS_ERROR'] += 1
elif "DEVICE_ERROR" in line:
stats_counter['DEVICE_ERROR'] += 1
else:
stats_counter['UNKNOWN_ERROR'] += 1
return render_template('stats.html', stats=stats_counter)

if name == 'main':
app.run(debug=True)

Error Logs body { font-family: Arial, sans-serif; margin: 20px; } pre { background-color: #f4f4f4; padding: 10px; border: 1px solid #ccc; overflow-x: auto; } nav { margin-bottom: 20px; } nav a { margin-right: 15px; text-decoration: none; color: #007BFF; } nav a:hover { text-decoration: underline; } Logs Statistics
Recent Error Logs
{% for line in logs %}
{{ line }}
{% endfor %}

Error Statistics body { font-family: Arial, sans-serif; margin: 20px; } nav { margin-bottom: 20px; } nav a { margin-right: 15px; text-decoration: none; color: #007BFF; } nav a:hover { text-decoration: underline; } table { width: 50%; border-collapse: collapse; } th, td { padding: 10px; border: 1px solid #ccc; text-align: left; } th { background-color: #f2f2f2; } Logs Statistics
Error Statistics
{% for error, count in stats.items() %} {% endfor %}
Error Type Count
{{ error }} {{ count }}
CC = gcc
CFLAGS = -Wall -Wextra -g -I$(SRC_DIR)
SRC_DIR = src
SIM_DIR = src/simulations
BUILD_DIR = build
LOG_DIR = logs

Create necessary directories
(shellmkdir−p(shell mkdir -p(shellmkdir−p(BUILD_DIR) $(LOG_DIR))

Source files
SRC_FILES = (SRCDIR)/logger.c (SRC_DIR)/logger.c (SRC
D
​
IR)/logger.c (SRC_DIR)/reporter.c
(SRCDIR)/recovery.c (SRC_DIR)/recovery.c (SRC
D
​
IR)/recovery.c (SRC_DIR)/error_handler.c

Simulation executables
SIMULATIONS = simulate_memory_error simulate_file_error simulate_device_error

all: $(SIMULATIONS)

simulate_memory_error: (SIMDIR)/simulatememoryerror.c(SIM_DIR)/simulate_memory_error.c(SIM
D
​
IR)/simulate
m
​
emory
e
​
rror.c(SRC_FILES)
(CC)(CC)(CC)(CFLAGS) (SIMDIR)/simulatememoryerror.c(SIM_DIR)/simulate_memory_error.c(SIM
D
​
IR)/simulate
m
​
emory
e
​
rror.c(SRC_FILES) -o $(BUILD_DIR)/simulate_memory_error

simulate_file_error: (SIMDIR)/simulatefileerror.c(SIM_DIR)/simulate_file_error.c(SIM
D
​
IR)/simulate
f
​
ile
e
​
rror.c(SRC_FILES)
(CC)(CC)(CC)(CFLAGS) (SIMDIR)/simulatefileerror.c(SIM_DIR)/simulate_file_error.c(SIM
D
​
IR)/simulate
f
​
ile
e
​
rror.c(SRC_FILES) -o $(BUILD_DIR)/simulate_file_error

simulate_device_error: (SIMDIR)/simulatedeviceerror.c(SIM_DIR)/simulate_device_error.c(SIM
D
​
IR)/simulate
d
​
evice
e
​
rror.c(SRC_FILES)
(CC)(CC)(CC)(CFLAGS) (SIMDIR)/simulatedeviceerror.c(SIM_DIR)/simulate_device_error.c(SIM
D
​
IR)/simulate
d
​
evice
e
​
rror.c(SRC_FILES) -o $(BUILD_DIR)/simulate_device_error

clean:
rm -rf $(BUILD_DIR)/*

.PHONY: all clean

everything works great when i do 
 build/simulate_memory_error leak

but this is not traacking in log file