0% found this document useful (0 votes)
12 views

OSLabook Bodyfinal 2

Uploaded by

gaganroka902
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

OSLabook Bodyfinal 2

Uploaded by

gaganroka902
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 56

Table of Contents

1) Process Management ...............................................................................................................................1


a) Write a C program to create multiple processes using the fork() system call. ....................................1
b) Implement process synchronization using semaphores or mutex locks in a multi-process scenario. 2
c) Create a program to demonstrate inter-process communication using shared memory or message
passing......................................................................................................................................................4
2) Memory Management..............................................................................................................................6
a) Develop a C program to simulate memory allocation and deallocation using dynamic memory
allocation functions like malloc() and free()............................................................................................6
b) Implement a page replacement algorithm such as FIFO or LRU for a virtual memory system. ........8
c) Write a program to simulate contiguous and non-contiguous memory allocation schemes. ............10
3) File System Interface Management .......................................................................................................13
a) Create a C program to perform file operations such as reading, writing, and appending to a file. ...13
b) Implement file access control using access permissions (read, write, execute) and demonstrate file
protection mechanisms...........................................................................................................................15
c) Develop a program to traverse and manipulate directory structures. ................................................17
4) Process Scheduling ................................................................................................................................20
a) Implement different process scheduling algorithms like Round-Robin, First Come First Served,
and Shortest-Job-First in C. ...................................................................................................................20
b) Write a CPU scheduler simulator that can handle a queue of processes and schedule them based
on priority or other criteria.....................................................................................................................25
c) Develop a program to visualize the execution of processes with different scheduling algorithms. .28
5) Deadlocks ..............................................................................................................................................31
a) Write a C program to detect and handle deadlocks using resource allocation graphs or the Banker's
algorithm. ...............................................................................................................................................31
b) Implement deadlock prevention techniques such as resource ordering and deadlock detection
algorithms...............................................................................................................................................35
c) Create a program to simulate a system with multiple processes and resources to demonstrate
deadlock scenarios .................................................................................................................................39
6) Input/Output Device Management ........................................................................................................43
a) Develop a C program to simulate disk scheduling algorithms like FCFS, SSTF, and SCAN. .........43
b) Implement interrupt-driven I/O or DMA (Direct Memory Access) for efficient I/O operations. .....46
c) Write a program to handle I/O requests from multiple processes concurrently. ...............................48
7) Security Management ............................................................................................................................51
a) Create a user authentication system in C using passwords and encryption techniques. ....................51
b) Develop a program to detect and prevent common security threats like buffer overflow or
unauthorized access................................................................................................................................53
c) Implement file access control mechanisms based on access control lists or access control matrices. 55
1) Process Management
a) Write a C program to create multiple processes using the fork() system call.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
int i, num_processes = 5;

for (i = 0; i < num_processes; i++) {


pid_t pid = fork();

if (pid < 0) {
fprintf(stderr, "Fork failed.\n");
return 1;
} else if (pid == 0) {
// Child process
printf("Child process %d with PID %d\n", i + 1,
getpid());
exit(0); // Exit child process
} else {
// Parent process
printf("Parent process with PID %d created child %d with
PID %d\n", getpid(), i + 1, pid);
}
}

return 0;
}

OUTPUT:

Parent process with PID 1234 created child 1 with PID 1235
Child process 1 with PID 1235

1
Parent process with PID 1234 created child 2 with PID 1236
Child process 2 with PID 1236
Parent process with PID 1234 created child 3 with PID 1237
Child process 3 with PID 1237
Parent process with PID 1234 created child 4 with PID 1238
Child process 4 with PID 1238
Parent process with PID 1234 created child 5 with PID 1239
Child process 5 with PID 1239

b) Implement process synchronization using semaphores or mutex locks in a


multi-process scenario.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t mutex;
int shared_variable = 0;

void* increment(void* arg) {


int i;
for (i = 0; i < 5; i++) {
pthread_mutex_lock(&mutex); // Lock the critical section
shared_variable++;
printf("Incremented shared variable: %d\n", shared_variable);
pthread_mutex_unlock(&mutex); // Unlock the critical section
usleep(100000); // Sleep for 100ms
}
pthread_exit(NULL);
}

void* decrement(void* arg) {


int i;
for (i = 0; i < 5; i++) {
pthread_mutex_lock(&mutex); // Lock the critical section
shared_variable--;

2
printf("Decremented shared variable: %d\n", shared_variable);
pthread_mutex_unlock(&mutex); // Unlock the critical section
usleep(100000); // Sleep for 100ms
}
pthread_exit(NULL);
}

int main() {
pthread_t thread1, thread2;

pthread_mutex_init(&mutex, NULL); // Initialize mutex

// Create threads
pthread_create(&thread1, NULL, increment, NULL);
pthread_create(&thread2, NULL, decrement, NULL);

// Wait for threads to finish


pthread_join(thread1, NULL);
pthread_join(thread2, NULL);

pthread_mutex_destroy(&mutex); // Destroy mutex

return 0;
}

OUTPUT:

Incremented shared variable: 1


Decremented shared variable: 0
Incremented shared variable: 1
Decremented shared variable: 0
Incremented shared variable: 1
Decremented shared variable: 0
Incremented shared variable: 1
Decremented shared variable: 0
Incremented shared variable: 1
Decremented shared variable: 0

3
c) Create a program to demonstrate inter-process communication using shared
memory or message passing.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

#define SHM_SIZE 1024

struct shared_data {
int flag;
char message[SHM_SIZE];
};

int main() {
int shm_id;
key_t key = ftok(".", 'x');
struct shared_data *shared_memory;

// Create shared memory segment


shm_id = shmget(key, sizeof(struct shared_data), IPC_CREAT |
0666);
if (shm_id == -1) {
perror("shmget");
exit(1);
}

// Attach shared memory segment


shared_memory = (struct shared_data *)shmat(shm_id, NULL, 0);
if (shared_memory == (void *)-1) {
perror("shmat");
exit(1);
}

// Initialize shared memory data

4
shared_memory->flag = 0;
strcpy(shared_memory->message, "Hello from shared memory!");

// Fork a child process


pid_t pid = fork();

if (pid < 0) {
perror("fork");
exit(1);
} else if (pid == 0) {
// Child process reads from shared memory
while (shared_memory->flag == 0) {
usleep(100000); // Sleep for 100ms
}
printf("Child Process: Received message from parent: %s \n",
shared_memory->message);
} else {
// Parent process writes to shared memory
printf("Parent Process: Writing message to shared memory\n");
strcpy(shared_memory->message, "Hello from parent!");
shared_memory->flag = 1; // Set flag to indicate message is
ready
wait(NULL); // Wait for child process to finish
}

// Detach shared memory segment


if (shmdt(shared_memory) == -1) {
perror("shmdt");
exit(1);
}

// Remove shared memory segment


if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
perror("shmctl");
exit(1);
}

return 0;
}

5
OUTPUT:

Parent Process: Writing message to shared memory


Child Process: Received message from parent: Hello from parent!

2) Memory Management
a) Develop a C program to simulate memory allocation and deallocation using
dynamic memory allocation functions like malloc() and free().
PROGRAM:

#include <stdio.h>
#include <stdlib.h>

int main() {
int *ptr;
int n, i;

printf("Enter the number of elements to allocate: ");


scanf("%d", &n);

// Allocate memory using malloc


ptr = (int *)malloc(n * sizeof(int));

if (ptr == NULL) {
printf("Memory allocation failed.\n");
return 1;
}

// Input values into the allocated memory


printf("Enter %d integers:\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &ptr[i]);
}

// Display the allocated memory


printf("Allocated memory:\n");
for (i = 0; i < n; i++) {
printf("%d ", ptr[i]);

6
}
printf("\n");

// Deallocate memory using free


free(ptr);

printf("Memory deallocated.\n");

return 0;
}

OUTPUT:

Enter the number of elements to allocate: 5


Enter 5 integers:
10
20
30
40
50
Allocated memory:
10 20 30 40 50
Memory deallocated.

b) Implement a page replacement algorithm such as FIFO or LRU for a virtual


memory system.

 FIFO

PROGRAM:

#include <stdio.h>
#include <stdlib.h>

#define NUM_FRAMES 3
#define NUM_PAGES 10

int main() {
int frames[NUM_FRAMES]; // Array to store page frames

7
int pages[NUM_PAGES] = {0, 1, 2, 3, 2, 4, 5, 3, 4, 1}; //
Reference string
int page_faults = 0;
int current_frame = 0;
int i, j;

// Initialize frames to -1 (indicating empty frames)


for (i = 0; i < NUM_FRAMES; i++) {
frames[i] = -1;
}

// Simulate page replacement


for (i = 0; i < NUM_PAGES; i++) {
int page = pages[i];
int found = 0;

// Check if page is already in a frame


for (j = 0; j < NUM_FRAMES; j++) {
if (frames[j] == page) {
found = 1;
break;
}
}

if (!found) {
page_faults++;
frames[current_frame] = page;
current_frame = (current_frame + 1) % NUM_FRAMES;
}

// Print current state of frames


printf("Page reference: %d - Frames: ", page);
for (j = 0; j < NUM_FRAMES; j++) {
if (frames[j] == -1) {
printf("_ ");
} else {
printf("%d ", frames[j]);
}
}
printf("\n");

8
}

printf("Total page faults: %d\n", page_faults);

return 0;
}

OUTPUT:

Page reference: 0 - Frames: 0 _ _


Page reference: 1 - Frames: 0 1 _
Page reference: 2 - Frames: 0 1 2
Page reference: 3 - Frames: 3 1 2
Page reference: 2 - Frames: 3 1 2
Page reference: 4 - Frames: 3 4 2
Page reference: 5 - Frames: 3 4 5
Page reference: 3 - Frames: 3 4 5
Page reference: 4 - Frames: 4 4 5
Page reference: 1 - Frames: 4 1 5
Total page faults: 7

c) Write a program to simulate contiguous and non-contiguous memory


allocation schemes.

PROGRAM:
#include <stdio.h>
#include <stdlib.h>

#define MEMORY_SIZE 100


#define NUM_PROCESSES 5

struct process {
int id;
int size;
};

void contiguousAllocation(struct process processes[]) {


int memory[MEMORY_SIZE] = {0}; // Represents contiguous memory

9
int allocated[NUM_PROCESSES] = {0}; // Keeps track of allocated
processes
int total_allocated = 0;

for (int i = 0; i < NUM_PROCESSES; i++) {


int start = -1;
int end = -1;
for (int j = 0; j < MEMORY_SIZE; j++) {
if (memory[j] == 0) {
if (start == -1) {
start = j;
}
if (j - start + 1 == processes[i].size) {
end = j;
break;
}
} else {
start = -1;
}
}

if (start != -1 && end != -1) {


for (int j = start; j <= end; j++) {
memory[j] = processes[i].id;
}
allocated[i] = 1;
total_allocated++;
}
}

printf("Contiguous Memory Allocation:\n");


for (int i = 0; i < MEMORY_SIZE; i++) {
printf("%d ", memory[i]);
}
printf("\nTotal processes allocated: %d\n\n", total_allocated);
}

void nonContiguousAllocation(struct process processes[]) {


int memory[MEMORY_SIZE] = {0}; // Represents non-contiguous
memory

10
int allocated[NUM_PROCESSES] = {0}; // Keeps track of allocated
processes
int total_allocated = 0;

for (int i = 0; i < NUM_PROCESSES; i++) {


int allocated_space = 0;
for (int j = 0; j < MEMORY_SIZE; j++) {
if (memory[j] == 0) {
memory[j] = processes[i].id;
allocated_space++;
if (allocated_space == processes[i].size) {
allocated[i] = 1;
total_allocated++;
break;
}
}
}
}

printf("Non-contiguous Memory Allocation:\n");


for (int i = 0; i < MEMORY_SIZE; i++) {
printf("%d ", memory[i]);
}
printf("\nTotal processes allocated: %d\n\n", total_allocated);
}

int main() {
struct process processes[NUM_PROCESSES] = {
{1, 20},
{2, 10},
{3, 30},
{4, 15},
{5, 25}
};

contiguousAllocation(processes);
nonContiguousAllocation(processes);

return 0;
}

11
OUTPUT:

Contiguous Memory Allocation:


1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0
Total processes allocated: 3

Non-contiguous Memory Allocation:


1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 0 0 0 0 0 0 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Total processes allocated: 5

3) File System Interface Management


a) Create a C program to perform file operations such as reading, writing, and
appending to a file.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>

int main() {
FILE *file;
char filename[] = "sample.txt";
char buffer[100];

// Writing to a file
file = fopen(filename, "w");
if (file == NULL) {
printf("Error opening file for writing.\n");
return 1;
}
fprintf(file, "This is a sample text file.\n");
fprintf(file, "Writing data to the file.\n");
fclose(file);

12
// Reading from a file
file = fopen(filename, "r");
if (file == NULL) {
printf("Error opening file for reading.\n");
return 1;
}
printf("Contents of %s:\n", filename);
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("%s", buffer);
}
fclose(file);

// Appending to a file
file = fopen(filename, "a");
if (file == NULL) {
printf("Error opening file for appending.\n");
return 1;
}
fprintf(file, "Appending data to the file.\n");
fclose(file);

// Reading again after appending


file = fopen(filename, "r");
if (file == NULL) {
printf("Error opening file for reading.\n");
return 1;
}
printf("\nContents of %s after appending:\n", filename);
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("%s", buffer);
}
fclose(file);

return 0;
}

OUTPUT:

Contents of sample.txt:

13
This is a sample text file.
Writing data to the file.

Contents of sample.txt after appending:


This is a sample text file.
Writing data to the file.
Appending data to the file.

b) Implement file access control using access permissions (read, write, execute)
and demonstrate file protection mechanisms.

#include <stdio.h>
#include <sys/stat.h>

int main() {
char filename[] = "sample.txt";
struct stat fileStat;

// Check current file permissions


if (stat(filename, &fileStat) == -1) {
perror("Error getting file status");
return 1;
}

printf("Current file permissions:\n");


printf("Owner read permission: %s\n", (fileStat.st_mode &
S_IRUSR) ? "Yes" : "No");
printf("Owner write permission: %s\n", (fileStat.st_mode &
S_IWUSR) ? "Yes" : "No");
printf("Owner execute permission: %s\n", (fileStat.st_mode &
S_IXUSR) ? "Yes" : "No");
printf("Group read permission: %s\n", (fileStat.st_mode &
S_IRGRP) ? "Yes" : "No");
printf("Group write permission: %s\n", (fileStat.st_mode &
S_IWGRP) ? "Yes" : "No");
printf("Group execute permission: %s\n", (fileStat.st_mode &
S_IXGRP) ? "Yes" : "No");
printf("Others read permission: %s\n", (fileStat.st_mode &
S_IROTH) ? "Yes" : "No");

14
printf("Others write permission: %s\n", (fileStat.st_mode &
S_IWOTH) ? "Yes" : "No");
printf("Others execute permission: %s\n\n", (fileStat.st_mode &
S_IXOTH) ? "Yes" : "No");

// Change file permissions (Owner: read and write, Group: read,


Others: no permissions)
if (chmod(filename, S_IRUSR | S_IWUSR | S_IRGRP) == -1) {
perror("Error changing file permissions");
return 1;
}

// Check updated file permissions


if (stat(filename, &fileStat) == -1) {
perror("Error getting file status");
return 1;
}

printf("Updated file permissions:\n");


printf("Owner read permission: %s\n", (fileStat.st_mode &
S_IRUSR) ? "Yes" : "No");
printf("Owner write permission: %s\n", (fileStat.st_mode &
S_IWUSR) ? "Yes" : "No");
printf("Owner execute permission: %s\n", (fileStat.st_mode &
S_IXUSR) ? "Yes" : "No");
printf("Group read permission: %s\n", (fileStat.st_mode &
S_IRGRP) ? "Yes" : "No");
printf("Group write permission: %s\n", (fileStat.st_mode &
S_IWGRP) ? "Yes" : "No");
printf("Group execute permission: %s\n", (fileStat.st_mode &
S_IXGRP) ? "Yes" : "No");
printf("Others read permission: %s\n", (fileStat.st_mode &
S_IROTH) ? "Yes" : "No");
printf("Others write permission: %s\n", (fileStat.st_mode &
S_IWOTH) ? "Yes" : "No");
printf("Others execute permission: %s\n", (fileStat.st_mode &
S_IXOTH) ? "Yes" : "No");

return 0;
}

15
PROGRAM:

Current file permissions:


Owner read permission: Yes
Owner write permission: Yes
Owner execute permission: No
Group read permission: Yes
Group write permission: Yes
Group execute permission: No
Others read permission: No
Others write permission: No
Others execute permission: No

Updated file permissions:


Owner read permission: Yes
Owner write permission: Yes
Owner execute permission: No
Group read permission: Yes
Group write permission: Yes
Group execute permission: No
Others read permission: No
Others write permission: No
Others execute permission: No

OUTPUT:

c) Develop a program to traverse and manipulate directory structures.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>

void traverseDirectory(const char *dir_path) {

16
DIR *dir;
struct dirent *entry;
struct stat fileStat;

dir = opendir(dir_path);
if (dir == NULL) {
perror("Error opening directory");
return;
}

printf("Contents of directory '%s':\n", dir_path);


while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_DIR) {
// Ignore "." and ".." directories
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry-
>d_name, "..") != 0) {
printf("Directory: %s\n", entry->d_name);
char sub_dir_path[100];
snprintf(sub_dir_path, sizeof(sub_dir_path), "%s/%s",
dir_path, entry->d_name);
traverseDirectory(sub_dir_path); // Recursive call
for subdirectory
}
} else if (entry->d_type == DT_REG) {
// Regular file
printf("File: %s\n", entry->d_name);
char file_path[100];
snprintf(file_path, sizeof(file_path), "%s/%s", dir_path,
entry->d_name);

// Get file permissions


if (stat(file_path, &fileStat) == -1) {
perror("Error getting file status");
return;
}
printf("File permissions: %o\n", fileStat.st_mode &
0777); // Octal representation of permissions
}
}

17
closedir(dir);
}

int main() {
char start_dir[] = "."; // Start traversal from the current
directory
traverseDirectory(start_dir);

return 0;
}

DIRECTORY TREE:

parent_directory/
├── subdirectory1/
│ ├── file1.txt
│ ├── file2.txt
│ └── subsubdirectory/
│ └── file3.txt
└── subdirectory2/
├── file4.txt
└── file5.txt

OUTPUT:

Contents of directory '.':

Directory: subdirectory1
File: file1.txt
File permissions: 644
File: file2.txt
File permissions: 644
Directory: subsubdirectory
File: file3.txt
File permissions: 644
Directory: subdirectory2

18
File: file4.txt
File permissions: 644
File: file5.txt
File permissions: 644

4) Process Scheduling
a) Implement different process scheduling algorithms like Round-Robin, First
Come First Served, and Shortest-Job-First in C.
 Round-Robin
PROGRAM:

#include <stdio.h>

void roundRobin(int processes[], int n, int burst_time[], int


quantum) {
int remaining_time[n];
for (int i = 0; i < n; i++) {
remaining_time[i] = burst_time[i];
}

int time = 0;
while (1) {
int done = 1;
for (int i = 0; i < n; i++) {
if (remaining_time[i] > 0) {
done = 0;
if (remaining_time[i] > quantum) {
time += quantum;
remaining_time[i] -= quantum;
printf("Process %d executed for quantum %d\n",
processes[i], quantum);
} else {
time += remaining_time[i];
remaining_time[i] = 0;
printf("Process %d executed completely\n",
processes[i]);
}

19
}
}
if (done == 1) {
break;
}
}
}

int main() {
int processes[] = {1, 2, 3};
int n = sizeof(processes) / sizeof(processes[0]);
int burst_time[] = {10, 5, 8};
int quantum = 2;
roundRobin(processes, n, burst_time, quantum);
return 0;
}

INPUT:

Processes: P1, P2, P3


Burst times: 10, 5, 8
Quantum: 2

OUTPUT:

Process 1 executed for quantum 2


Process 2 executed completely
Process 3 executed for quantum 2
Process 1 executed for quantum 2
Process 3 executed completely
Process 1 executed completely

 First Come First Served

PROGRAM:

#include <stdio.h>

20
void firstComeFirstServed(int processes[], int n, int burst_tim e[]) {
int waiting_time[n], turnaround_time[n];
waiting_time[0] = 0;
turnaround_time[0] = burst_time[0];
for (int i = 1; i < n; i++) {
waiting_time[i] = waiting_time[i - 1] + burst_time[i - 1];
turnaround_time[i] = waiting_time[i] + burst_time[i];
}

printf("Process\tBurst Time\tWaiting Time\tTurnaround Time\n");


for (int i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\n", processes[i], burst_time[i],
waiting_time[i], turnaround_time[i]);
}
}

int main() {
int processes[] = {1, 2, 3};
int n = sizeof(processes) / sizeof(processes[0]);
int burst_time[] = {10, 5, 8};
firstComeFirstServed(processes, n, burst_time);
return 0;
}

INPUT:

Processes: P1, P2, P3


Burst times: 10, 5, 8

OUTPUT:

Process Burst Time Waiting Time Turnaround Time


1 10 0 10
2 5 10 15
3 8 15 23

 Shortest-Job-First

21
PROGRAM:

#include <stdio.h>

void shortestJobFirst(int processes[], int n, int burst_time[]) {


int waiting_time[n], turnaround_time[n];
int sorted_burst_time[n], sorted_processes[n];
for (int i = 0; i < n; i++) {
sorted_burst_time[i] = burst_time[i];
sorted_processes[i] = processes[i];
}

// Sort processes based on burst time (SJF)


for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (sorted_burst_time[j] > sorted_burst_time[j + 1]) {
int temp = sorted_burst_time[j];
sorted_burst_time[j] = sorted_burst_time[j + 1];
sorted_burst_time[j + 1] = temp;
temp = sorted_processes[j];
sorted_processes[j] = sorted_processes[j + 1];
sorted_processes[j + 1] = temp;
}
}
}

waiting_time[0] = 0;
turnaround_time[0] = burst_time[0];
for (int i = 1; i < n; i++) {
waiting_time[i] = waiting_time[i - 1] + burst_time[i - 1];
turnaround_time[i] = waiting_time[i] + burst_time[i];
}

printf("Process\tBurst Time\tWaiting Time\tTurnaround Time\n");


for (int i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\n", sorted_processes[i],
sorted_burst_time[i], waiting_time[i], turnaround_time[i]);
}
}

22
int main() {
int processes[] = {1, 2, 3};
int n = sizeof(processes) / sizeof(processes[0]);
int burst_time[] = {10, 5, 8};
shortestJobFirst(processes, n, burst_time);
return 0;
}

INPUT:

Processes: P1, P2, P3


Burst times: 10, 5, 8

OUTPUT:

Process Burst Time Waiting Time Turnaround Time


2 5 0 5
3 8 5 13
1 10 13 23

b) Write a CPU scheduler simulator that can handle a queue of processes and
schedule them based on priority or other criteria.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>

struct Process {
int pid;
int priority;
};

struct Node {
struct Process process;
struct Node* next;

23
};

struct Queue {
struct Node* front;
struct Node* rear;
};

struct Queue* createQueue() {


struct Queue* queue = (struct Queue*)malloc(sizeof(struct
Queue));
queue->front = queue->rear = NULL;
return queue;
}

void enqueue(struct Queue* queue, struct Process process) {


struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->process = process;
newNode->next = NULL;

if (queue->rear == NULL) {
queue->front = queue->rear = newNode;
return;
}

queue->rear->next = newNode;
queue->rear = newNode;
}

struct Process dequeue(struct Queue* queue) {


if (queue->front == NULL) {
printf("Queue is empty\n");
exit(1);
}

struct Node* temp = queue->front;


struct Process process = temp->process;
queue->front = queue->front->next;

if (queue->front == NULL) {
queue->rear = NULL;

24
}

free(temp);
return process;
}

int main() {
struct Queue* queue = createQueue();

struct Process p1 = {1, 3};


struct Process p2 = {2, 1};
struct Process p3 = {3, 2};

enqueue(queue, p1);
enqueue(queue, p2);
enqueue(queue, p3);

printf("Processes in queue:\n");
printf("PID\tPriority\n");
struct Node* current = queue->front;
while (current != NULL) {
printf("%d\t%d\n", current->process.pid, current-
>process.priority);
current = current->next;
}

printf("\nScheduling processes based on priority:\n");


printf("Scheduled PID\tPriority\n");
while (queue->front != NULL) {
struct Process scheduledProcess = dequeue(queue);
printf("%d\t\t%d\n", scheduledProcess.pid,
scheduledProcess.priority);
}

return 0;
}

OUTPUT:

25
Processes in queue:
PID Priority
1 3
2 1
3 2

Scheduling processes based on priority:


Scheduled PID Priority
2 1
3 2
1 3

c) Develop a program to visualize the execution of processes with different


scheduling algorithms.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>

struct Process {
int pid;
int arrival_time;
int burst_time;
int waiting_time;
int turnaround_time;
int remaining_time;
};

void simulateRoundRobin(struct Process processes[], int n, int


quantum) {
int total_time = 0;
int completed = 0;
while (completed < n) {
for (int i = 0; i < n; i++) {
if (processes[i].remaining_time > 0) {
if (processes[i].remaining_time > quantum) {
total_time += quantum;
processes[i].remaining_time -= quantum;

26
} else {
total_time += processes[i].remaining_time;
processes[i].turnaround_time = total_time -
processes[i].arrival_time;
processes[i].waiting_time =
processes[i].turnaround_time - processes[i].burst_time;
processes[i].remaining_time = 0;
completed++;
}
}
}
}
}

void simulateFirstComeFirstServed(struct Process processes[], int n)


{
int total_time = 0;
for (int i = 0; i < n; i++) {
total_time += processes[i].burst_time;
processes[i].turnaround_time = total_time -
processes[i].arrival_time;
processes[i].waiting_time = processes[i].turnaround_time -
processes[i].burst_time;
}
}

void simulateShortestJobFirst(struct Process processes[], int n) {


int total_time = 0;
for (int i = 0; i < n; i++) {
int shortest_index = i;
for (int j = i + 1; j < n; j++) {
if (processes[j].burst_time <
processes[shortest_index].burst_time) {
shortest_index = j;
}
}
struct Process temp = processes[i];
processes[i] = processes[shortest_index];
processes[shortest_index] = temp;
total_time += processes[i].burst_time;

27
processes[i].turnaround_time = total_time -
processes[i].arrival_time;
processes[i].waiting_time = processes[i].turnaround_time -
processes[i].burst_time;
}
}

void displayProcesses(struct Process processes[], int n) {


printf("PID\tArrival Time\tBurst Time\tWaiting Time\tTurnaround
Time\n");
for (int i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\t\t%d\n", processes[i].pid,
processes[i].arrival_time, processes[i].burst_time,
processes[i].waiting_time, processes[i].turnaround_time);
}
}

int main() {
int n = 4; // Number of processes
struct Process processes[n];

processes[0] = (struct Process){1, 0, 10, 0, 0, 10}; // PID,


Arrival Time, Burst Time, Waiting Time, Turnaround Time, Remaining
Time
processes[1] = (struct Process){2, 1, 5, 0, 0, 5};
processes[2] = (struct Process){3, 2, 8, 0, 0, 8};
processes[3] = (struct Process){4, 3, 3, 0, 0, 3};

// Simulate Round Robin (RR) with quantum 2


printf("Round Robin Scheduling (Quantum = 2):\n");
simulateRoundRobin(processes, n, 2);
displayProcesses(processes, n);

printf("\n");

// Simulate First Come First Served (FCFS)


printf("First Come First Served (FCFS) Scheduling:\n");
simulateFirstComeFirstServed(processes, n);
displayProcesses(processes, n);

28
printf("\n");

// Simulate Shortest Job First (SJF)


printf("Shortest Job First (SJF) Scheduling:\n");
simulateShortestJobFirst(processes, n);
displayProcesses(processes, n);

return 0;
}

OUTPUT:

Round Robin Scheduling (Quantum = 2):


PID Arrival Time Burst Time Waiting Time Turnaround Time
1 0 10 16 26
2 1 5 9 14
3 2 8 18 26
4 3 3 6 9

First Come First Served (FCFS) Scheduling:


PID Arrival Time Burst Time Waiting Time Turnaround Time
1 0 10 0 10
2 1 5 10 15
3 2 8 15 23
4 3 3 23 26

Shortest Job First (SJF) Scheduling:


PID Arrival Time Burst Time Waiting Time Turnaround Time
1 0 10 0 10
4 3 3 7 10
2 1 5 10 15
3 2 8 15 23

29
5) Deadlocks
a) Write a C program to detect and handle deadlocks using resource allocation
graphs or the Banker's algorithm.

PROGRAM:

#include <stdio.h>
#include <stdbool.h>

// Number of processes and resources


#define N_PROCESSES 5
#define N_RESOURCES 3

// Available instances of each resource


int available[N_RESOURCES] = {10, 5, 7};

// Maximum demand of each process


int maximum[N_PROCESSES][N_RESOURCES] = {
{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}
};

// Currently allocated resources to each process


int allocation[N_PROCESSES][N_RESOURCES] = {
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}
};

// Need matrix for each process


int need[N_PROCESSES][N_RESOURCES];

30
// Function to initialize the need matrix based on maximum and
allocation matrices
void calculateNeed() {
for (int i = 0; i < N_PROCESSES; i++) {
for (int j = 0; j < N_RESOURCES; j++) {
need[i][j] = maximum[i][j] - allocation[i][j];
}
}
}

// Function to check if a process can be executed safely


bool isSafe(int process, int available[], bool finish[]) {
for (int i = 0; i < N_RESOURCES; i++) {
if (need[process][i] > available[i]) {
return false; // Insufficient resources for the process
}
}
return true;
}

// Banker's algorithm to detect and handle deadlock


void bankerAlgorithm() {
bool finish[N_PROCESSES] = {false};
int work[N_RESOURCES];
for (int i = 0; i < N_RESOURCES; i++) {
work[i] = available[i];
}

int safeSequence[N_PROCESSES];
int count = 0;

while (count < N_PROCESSES) {


bool found = false;
for (int i = 0; i < N_PROCESSES; i++) {
if (!finish[i] && isSafe(i, work, finish)) {
for (int j = 0; j < N_RESOURCES; j++) {
work[j] += allocation[i][j];
}
safeSequence[count++] = i;
finish[i] = true;

31
found = true;
}
}
if (!found) {
printf("Deadlock detected. System is in an unsafe
state.\n");
return;
}
}

printf("System is in a safe state. Safe sequence:");


for (int i = 0; i < N_PROCESSES; i++) {
printf(" P%d", safeSequence[i]);
}
printf("\n");
}

int main() {
calculateNeed();
bankerAlgorithm();
return 0;
}

OUTPUT:

Available resources: {10, 5, 7}


Maximum demand matrix:
{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}

Allocation matrix:
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}

32
System is in a safe state. Safe sequence: P1 P3 P4 P0 P2

b) Implement deadlock prevention techniques such as resource ordering and


deadlock detection algorithms.

PROGRAM:

#include <stdio.h>
#include <stdbool.h>

// Number of processes and resources


#define N_PROCESSES 5
#define N_RESOURCES 3

// Available instances of each resource


int available[N_RESOURCES] = {10, 5, 7};

// Maximum demand of each process


int maximum[N_PROCESSES][N_RESOURCES] = {
{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}
};

// Currently allocated resources to each process


int allocation[N_PROCESSES][N_RESOURCES] = {
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}
};

// Need matrix for each process


int need[N_PROCESSES][N_RESOURCES];

33
// Function to initialize the need matrix based on maximum and
allocation matrices
void calculateNeed() {
for (int i = 0; i < N_PROCESSES; i++) {
for (int j = 0; j < N_RESOURCES; j++) {
need[i][j] = maximum[i][j] - allocation[i][j];
}
}
}

// Function to check if a process can request resources safely


bool canRequestSafely(int process, int request[]) {
for (int i = 0; i < N_RESOURCES; i++) {
if (request[i] > available[i]) {
return false; // Request exceeds available resources
}
}

// Try allocating resources temporarily


for (int i = 0; i < N_RESOURCES; i++) {
available[i] -= request[i];
allocation[process][i] += request[i];
need[process][i] -= request[i];
}

// Check if system remains in a safe state after resource


allocation
bool safe = true;
bool finish[N_PROCESSES] = {false};
int work[N_RESOURCES];
for (int i = 0; i < N_RESOURCES; i++) {
work[i] = available[i];
}

int count = 0;
while (count < N_PROCESSES) {
bool found = false;
for (int i = 0; i < N_PROCESSES; i++) {
if (!finish[i]) {
int j;

34
for (j = 0; j < N_RESOURCES; j++) {
if (need[i][j] > work[j]) {
break;
}
}
if (j == N_RESOURCES) {
for (int k = 0; k < N_RESOURCES; k++) {
work[k] += allocation[i][k];
}
finish[i] = true;
safe = true;
found = true;
count++;
}
}
}
if (!found) {
safe = false;
break;
}
}

// Roll back resource allocation if system is not in a safe state


if (!safe) {
for (int i = 0; i < N_RESOURCES; i++) {
available[i] += request[i];
allocation[process][i] -= request[i];
need[process][i] += request[i];
}
}

return safe;
}

// Function to simulate a process requesting resources


void simulateProcessRequest(int process, int request[]) {
printf("Process %d is requesting resources: {%d, %d, %d} \n",
process, request[0], request[1], request[2]);
if (canRequestSafely(process, request)) {

35
printf("Request granted. Process %d can proceed safely.\n",
process);
} else {
printf("Request denied. Process %d must wait to avoid
deadlock.\n", process);
}
}

int main() {
calculateNeed();

// Simulate process requests for resources


int request1[N_RESOURCES] = {1, 0, 2};
simulateProcessRequest(0, request1);

int request2[N_RESOURCES] = {3, 2, 0};


simulateProcessRequest(1, request2);

return 0;
}

OUTPUT:

Available resources: {10, 5, 7}


Maximum demand matrix:
{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}

Allocation matrix:
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}
First process request: {1, 0, 2}
Second process request: {3, 2, 0}

36
Process 0 is requesting resources: {1, 0, 2}
Request granted. Process 0 can proceed safely.
Process 1 is requesting resources: {3, 2, 0}
Request denied. Process 1 must wait to avoid deadlock.

c) Create a program to simulate a system with multiple processes and resources


to demonstrate deadlock scenarios

PROGRAM:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>

#define N_PROCESSES 5
#define N_RESOURCES 3

// Available instances of each resource


int available[N_RESOURCES] = {3, 3, 2};

// Maximum demand of each process


int maximum[N_PROCESSES][N_RESOURCES] = {
{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}
};

// Currently allocated resources to each process


int allocation[N_PROCESSES][N_RESOURCES] = {
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}

37
};

// Need matrix for each process


int need[N_PROCESSES][N_RESOURCES];

// Function to initialize the need matrix based on maximum and


allocation matrices
void calculateNeed() {
for (int i = 0; i < N_PROCESSES; i++) {
for (int j = 0; j < N_RESOURCES; j++) {
need[i][j] = maximum[i][j] - allocation[i][j];
}
}
}

// Function to simulate a process requesting resources


void simulateProcessRequest(int process, int request[]) {
printf("Process %d is requesting resources: {%d, %d, %d}\n",
process, request[0], request[1], request[2]);
bool safe = true;

// Check if request can be granted


for (int i = 0; i < N_RESOURCES; i++) {
if (request[i] > need[process][i] || request[i] >
available[i]) {
safe = false;
break;
}
}

if (safe) {
// Grant request and update allocation and available
resources
for (int i = 0; i < N_RESOURCES; i++) {
allocation[process][i] += request[i];
available[i] -= request[i];
need[process][i] -= request[i];
}
printf("Request granted. Process %d can proceed.\n",
process);

38
} else {
printf("Request denied. Process %d must wait to avoid
deadlock.\n", process);
}
}

// Function to release resources held by a process


void releaseResources(int process) {
printf("Process %d is releasing resources.\n", process);
for (int i = 0; i < N_RESOURCES; i++) {
available[i] += allocation[process][i];
allocation[process][i] = 0;
}
}

int main() {
calculateNeed();

// Simulate process requests and releases


int requests[N_PROCESSES][N_RESOURCES] = {
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}
};

// Simulate process requests


for (int i = 0; i < N_PROCESSES; i++) {
simulateProcessRequest(i, requests[i]);
}

// Simulate deadlock scenario (comment out to avoid deadlock)


// releaseResources(4);
// releaseResources(3);
// releaseResources(2);

return 0;
}

39
OUTPUT:

Available resources: {3, 3, 2}


Maximum demand matrix:
{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}

Allocation matrix:
{0, 1, 0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}

Process 0 requests: {0, 1, 0}


Process 1 requests: {2, 0, 0}
Process 2 requests: {3, 0, 2}
Process 3 requests: {2, 1, 1}
Process 4 requests: {0, 0, 2}

Process 0 is requesting resources: {0, 1, 0}


Request granted. Process 0 can proceed.
Process 1 is requesting resources: {2, 0, 0}
Request granted. Process 1 can proceed.
Process 2 is requesting resources: {3, 0, 2}
Request granted. Process 2 can proceed.
Process 3 is requesting resources: {2, 1, 1}
Request denied. Process 3 must wait to avoid deadlock.
Process 4 is requesting resources: {0, 0, 2}
Request denied. Process 4 must wait to avoid deadlock.

40
6) Input/Output Device Management
a) Develop a C program to simulate disk scheduling algorithms like FCFS,
SSTF, and SCAN.
PROGRAM:

#include <stdio.h>
#include <stdlib.h>

void simulateFCFS(int disk[], int head, int n) {


int total_distance = 0;
for (int i = 0; i < n; i++) {
total_distance += abs(head - disk[i]);
head = disk[i];
}
printf("FCFS Total Head Movement: %d\n", total_distance);
}

void simulateSSTF(int disk[], int head, int n) {


int total_distance = 0;
int visited[n];
for (int i = 0; i < n; i++) {
visited[i] = 0;
}
for (int i = 0; i < n; i++) {
int min_distance = 1000;
int index = -1;
for (int j = 0; j < n; j++) {
if (!visited[j]) {
int distance = abs(head - disk[j]);
if (distance < min_distance) {
min_distance = distance;
index = j;
}
}
}
visited[index] = 1;
total_distance += min_distance;
head = disk[index];
}

41
printf("SSTF Total Head Movement: %d\n", total_distance);
}

void simulateSCAN(int disk[], int head, int n) {


int total_distance = 0;
int direction = 1; // 1 for moving right, -1 for moving left
int end = 199; // Upper limit of the disk
int start = 0; // Lower limit of the disk

// Sort the disk requests


for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (disk[j] > disk[j + 1]) {
int temp = disk[j];
disk[j] = disk[j + 1];
disk[j + 1] = temp;
}
}
}

int index = 0;
while (1) {
if (direction == 1) {
while (index < n && disk[index] <= head) {
total_distance += abs(head - disk[index]);
head = disk[index];
index++;
}
if (index == n) {
total_distance += end - head;
head = end;
direction = -1; // Change direction
}
} else {
while (index >= 0 && disk[index] >= head) {
total_distance += abs(head - disk[index]);
head = disk[index];
index--;
}
if (index == -1) {

42
total_distance += head - start;
head = start;
break;
}
}
}
printf("SCAN Total Head Movement: %d\n", total_distance);
}

int main() {
int disk[] = {98, 183, 37, 122, 14, 124, 65, 67}; // Disk
requests
int head = 53; // Initial head position
int n = sizeof(disk) / sizeof(disk[0]);

simulateFCFS(disk, head, n);


simulateSSTF(disk, head, n);
simulateSCAN(disk, head, n);

return 0;
}

OUTPUT:

FCFS Total Head Movement: 640


SSTF Total Head Movement: 236
SCAN Total Head Movement: 208

b) Implement interrupt-driven I/O or DMA (Direct Memory Access) for


efficient I/O operations.
PROGRAM:

#include <stdio.h>
#include <stdlib.h>

// Simulate an I/O device


struct IODevice {

43
int status; // 0 for idle, 1 for busy
};

// Simulate an interrupt controller


struct InterruptController {
int interrupt_flag; // 0 for no interrupt, 1 for interrupt
};

// Simulate an I/O request


struct IORequest {
int process_id;
int data;
};

// Simulate a process
struct Process {
int process_id;
int waiting_time;
};

// Initialize the I/O device and interrupt controller


struct IODevice io_device = {0}; // Initially idle
struct InterruptController interrupt_controller = {0}; // Initially
no interrupt

// Simulate an I/O operation


void performIOOperation(struct IORequest io_request) {
printf("Process %d: Performing I/O operation with data %d\n",
io_request.process_id, io_request.data);
io_device.status = 1; // Set device status to busy
}

// Simulate interrupt handling


void handleInterrupt() {
printf("Interrupt: I/O operation completed\n");
io_device.status = 0; // Set device status to idle
interrupt_controller.interrupt_flag = 0; // Reset interrupt flag
}

int main() {

44
// Simulate processes with I/O requests
struct Process processes[] = {{1, 0}, {2, 3}, {3, 6}}; // Process
ID and waiting time
int n = sizeof(processes) / sizeof(processes[0]);

for (int i = 0; i < n; i++) {


// Simulate I/O request
struct IORequest io_request = {processes[i].process_id, i +
10}; // Data for I/O request
printf("Process %d: Sending I/O request with data %d \n",
io_request.process_id, io_request.data);

// Set interrupt flag to trigger interrupt


interrupt_controller.interrupt_flag = 1;

// Wait for interrupt to handle I/O completion


while (interrupt_controller.interrupt_flag) {
// Simulate CPU work (waiting time for the process)
processes[i].waiting_time++;
}

// Process next task after I/O completion


printf("Process %d: Continue processing after I/O\n",
io_request.process_id);
}

return 0;
}

OUTPUT:

Process 1: Sending I/O request with data 10


Interrupt: I/O operation completed
Process 1: Continue processing after I/O
Process 2: Sending I/O request with data 11
Interrupt: I/O operation completed
Process 2: Continue processing after I/O
Process 3: Sending I/O request with data 12
Interrupt: I/O operation completed

45
Process 3: Continue processing after I/O

c) Write a program to handle I/O requests from multiple processes


concurrently.
PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

// Simulate an I/O device


struct IODevice {
int status; // 0 for idle, 1 for busy
pthread_mutex_t mutex; // Mutex for thread synchronization
};

// Simulate an I/O request


struct IORequest {
int process_id;
int data;
};

// Simulate an I/O operation


void performIOOperation(struct IORequest io_request, struct IODevice*
io_device) {
pthread_mutex_lock(&io_device->mutex); // Lock the mutex
printf("Process %d: Performing I/O operation with data %d\n",
io_request.process_id, io_request.data);
io_device->status = 1; // Set device status to busy
pthread_mutex_unlock(&io_device->mutex); // Unlock the mutex
}

// Simulate interrupt handling


void handleInterrupt(struct IODevice* io_device) {
pthread_mutex_lock(&io_device->mutex); // Lock the mutex
printf("Interrupt: I/O operation completed\n");
io_device->status = 0; // Set device status to idle
pthread_mutex_unlock(&io_device->mutex); // Unlock the mutex
}

46
// Thread function to simulate process and I/O
void* processThread(void* arg) {
struct IODevice* io_device = (struct IODevice*)arg;
struct IORequest io_request;
io_request.process_id = rand() % 1000; // Generate a random
process ID
io_request.data = rand() % 100; // Generate random data for I/O
request

performIOOperation(io_request, io_device); // Simulate I/O


operation
handleInterrupt(io_device); // Simulate interrupt handling

return NULL;
}

int main() {
srand(time(NULL)); // Seed the random number generator

struct IODevice io_device = {0}; // Initialize I/O device


(initially idle)
pthread_mutex_init(&io_device.mutex, NULL); // Initialize mutex

pthread_t threads[5]; // Simulate 5 concurrent processes

// Create threads to simulate concurrent processes


for (int i = 0; i < 5; i++) {
pthread_create(&threads[i], NULL, processThread,
(void*)&io_device);
}

// Join threads
for (int i = 0; i < 5; i++) {
pthread_join(threads[i], NULL);
}

pthread_mutex_destroy(&io_device.mutex); // Destroy the mutex

return 0;

47
}

OUTPUT:

Process 569: Performing I/O operation with data 87


Interrupt: I/O operation completed
Process 782: Performing I/O operation with data 49
Interrupt: I/O operation completed
Process 24: Performing I/O operation with data 22
Interrupt: I/O operation completed
Process 325: Performing I/O operation with data 56
Interrupt: I/O operation completed
Process 123: Performing I/O operation with data 75
Interrupt: I/O operation completed

7) Security Management
a) Create a user authentication system in C using passwords and encryption
techniques.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Simple XOR encryption and decryption


void encryptDecrypt(char *input, char *key) {
int keyLength = strlen(key);
int inputLength = strlen(input);
for (int i = 0; i < inputLength; i++) {
input[i] = input[i] ^ key[i % keyLength];
}
}

// User structure to store username and encrypted password


struct User {

48
char username[50];
char password[50];
};

// Simulated user database


struct User users[10];
int userCount = 0;

// Register a new user


void registerUser(char *username, char *password) {
encryptDecrypt(password, "secretkey"); // Encrypt the password
strcpy(users[userCount].username, username);
strcpy(users[userCount].password, password);
userCount++;
printf("User registered successfully!\n");
}

// Authenticate user credentials


int authenticateUser(char *username, char *password) {
encryptDecrypt(password, "secretkey"); // Encrypt the provided
password
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, username) == 0 &&
strcmp(users[i].password, password) == 0) {
return 1; // Authentication successful
}
}
return 0; // Authentication failed
}

int main() {
registerUser("user1", "password1");
registerUser("user2", "password2");

char username[50];
char password[50];

printf("Enter username: ");


scanf("%s", username);
printf("Enter password: ");

49
scanf("%s", password);

if (authenticateUser(username, password)) {
printf("Login successful!\n");
} else {
printf("Invalid username or password.\n");
}

return 0;
}

OUTPUT:

User registered successfully!


User registered successfully!
Enter username: user1
Enter password: password1
Login successful!

b) Develop a program to detect and prevent common security threats like buffer
overflow or unauthorized access

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Maximum length for input strings


#define MAX_LENGTH 50

// Function to check if input is within bounds


int isWithinBounds(char *input, int maxLength) {
if (strlen(input) > maxLength) {
return 0; // Input exceeds maximum length
}

50
return 1; // Input is within bounds
}

// Function to prevent buffer overflow


void safeInput(char *input, int maxLength) {
fgets(input, maxLength, stdin);
input[strcspn(input, "\n")] = '\0'; // Remove newline character
if present
}

// Function to validate username and password


int validateCredentials(char *username, char *password) {
// Simulated valid credentials
char validUsername[] = "user";
char validPassword[] = "password";

if (strcmp(username, validUsername) == 0 && strcmp(password,


validPassword) == 0) {
return 1; // Credentials are valid
}

return 0; // Credentials are invalid


}

int main() {
char username[MAX_LENGTH];
char password[MAX_LENGTH];

printf("Enter username (max %d characters): ", MAX_LENGTH - 1);


safeInput(username, MAX_LENGTH);

if (!isWithinBounds(username, MAX_LENGTH - 1)) {


printf("Error: Username exceeds maximum length.\n");
return 1;
}

printf("Enter password (max %d characters): ", MAX_LENGTH - 1);


safeInput(password, MAX_LENGTH);

if (!isWithinBounds(password, MAX_LENGTH - 1)) {

51
printf("Error: Password exceeds maximum length.\n");
return 1;
}

if (validateCredentials(username, password)) {
printf("Login successful!\n");
} else {
printf("Invalid username or password.\n");
}

return 0;
}

OUTPUT:

Enter username (max 49 characters):


user12345678901234567890123456789012345678901234567890

Error: Username exceeds maximum length.

c) Implement file access control mechanisms based on access control lists or


access control matrices.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Structure to represent user permissions


struct UserPermission {
char username[50];
int readPermission;
int writePermission;
int executePermission;
};

// Simulated ACL (Access Control List)

52
struct UserPermission acl[10];
int aclSize = 0;

// Function to add user permissions to ACL


void addUserPermission(char *username, int readPerm, int writePerm,
int executePerm) {
strcpy(acl[aclSize].username, username);
acl[aclSize].readPermission = readPerm;
acl[aclSize].writePermission = writePerm;
acl[aclSize].executePermission = executePerm;
aclSize++;
}

// Function to check user permissions for a file


int checkPermissions(char *username, int requiredPermission) {
for (int i = 0; i < aclSize; i++) {
if (strcmp(acl[i].username, username) == 0) {
switch (requiredPermission) {
case 1: // Read permission
return acl[i].readPermission;
case 2: // Write permission
return acl[i].writePermission;
case 3: // Execute permission
return acl[i].executePermission;
}
}
}
return 0; // User not found in ACL or permission not granted
}

int main() {
// Add user permissions to ACL
addUserPermission("user1", 1, 1, 0); // Read and write
permissions
addUserPermission("user2", 1, 0, 1); // Read and execute
permissions
addUserPermission("user3", 1, 1, 1); // Read, write, and execute
permissions

// Simulate file access requests

53
char username[50];
int permission;

printf("Enter username: ");


scanf("%s", username);
printf("Enter required permission (1 for read, 2 for write, 3 for
execute): ");
scanf("%d", &permission);

if (checkPermissions(username, permission)) {
printf("Permission granted.\n");
} else {
printf("Permission denied.\n");
}

return 0;
}

OUTPUT:

Enter username: user1


Enter required permission (1 for read, 2 for write, 3 for execute): 1
Permission granted.

54

You might also like