ASSIGNMENT 2: Operating System Shell and its working
SET A:
1) Write a C program that behaves like a shell which displays the command
prompt ‘myshell$’. Itaccepts the command, tokenize the command line and
execute it by creating the child process. Also implement the additional
command ‘count’ as
myshell$ count c filename: It will display the number of characters in given file
myshell$ count w filename: It will display the number of words in given file
myshell$ count l filename: It will display the number of lines in given file
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_CMD_LEN 1024
#define MAX_ARGS 64
// Function to count characters, words, or lines in a file
void count_file(const char *mode, const char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
perror("File error");
return;
}
int ch, count = 0;
if (strcmp(mode, "c") == 0) { // Count characters
while ((ch = fgetc(fp)) != EOF)
count++;
printf("Characters: %d\n", count);
} else if (strcmp(mode, "w") == 0) { // Count words
int in_word = 0;
while ((ch = fgetc(fp)) != EOF) {
if (ch == ' ' || ch == '\n' || ch == '\t') {
in_word = 0;
} else if (!in_word) {
in_word = 1;
count++;
} }
printf("Words: %d\n", count);
} else if (strcmp(mode, "l") == 0) { // Count lines
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
count++;
}
printf("Lines: %d\n", count);
} else {
printf("Invalid mode for count. Use c, w, or l.\n");
}
fclose(fp);
}
// Function to parse the input line into arguments
void parse_input(char *input, char **args) {
int i = 0;
args[i] = strtok(input, " \t\n");
while (args[i] != NULL) {
i++;
args[i] = strtok(NULL, " \t\n");
} }
int main() {
char input[MAX_CMD_LEN];
char *args[MAX_ARGS];
while (1) {
printf("myshell$ ");
fflush(stdout);
if (fgets(input, sizeof(input), stdin) == NULL) {
printf("\n");
break;
}
// Remove trailing newline
input[strcspn(input, "\n")] = '\0';
// Skip empty input
if (strlen(input) == 0)
continue;
parse_input(input, args);
// Handle built-in exit
if (strcmp(args[0], "exit") == 0) {
break;
}
// Handle custom 'count' command
if (strcmp(args[0], "count") == 0) {
if (args[1] && args[2]) {
count_file(args[1], args[2]);
} else {
printf("Usage: count [c|w|l] filename\n");
}
continue;
}
// Fork for external command
pid_t pid = fork();
if (pid < 0) {
perror("Fork failed");
} else if (pid == 0) {
// Child process
if (execvp(args[0], args) == -1) {
perror("Command execution failed");
}
exit(EXIT_FAILURE);
} else {
// Parent process
wait(NULL);
}
}
return 0;
}
OUTPUT:
SET B:
1) Write a C program that behaves like a shell which displays the command
prompt ‘myshell$’. It accepts the command, tokenize the command line and
execute it by creating the child process. Also implement the additional
command ‘list’ as
myshell$ list f dirname: It will display filenames in given directory.
myshell$ list n dirname: It will count the number of entries in given directory.
myshell$ list i dirname: It will display filenames and their inode number for the
files in a given Directory.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#define MAX_CMD_LEN 1024
#define MAX_ARGS 100
// Function to handle 'list' command
void handle_list(char *option, char *dirname) {
DIR *dir;
struct dirent *entry;
int count = 0;
if ((dir = opendir(dirname)) == NULL) {
perror("Unable to open directory");
return;
}
if (strcmp(option, "f") == 0) {
// List filenames
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
printf("%s\n", entry->d_name);
}
} else if (strcmp(option, "n") == 0) {
// Count entries
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
count++;
}
printf("Total entries: %d\n", count);
} else if (strcmp(option, "i") == 0) {
// List filenames with inode numbers
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
printf("%s (Inode: %lu)\n", entry->d_name, entry->d_ino);
}
} else {
printf("Invalid option for list command. Use: f, n, or i\n");
}
closedir(dir);
}
// Function to parse and execute command
void execute_command(char *cmdline) {
char *args[MAX_ARGS];
char *token;
int arg_count = 0;
// Tokenize the input
token = strtok(cmdline, " \t\n");
while (token != NULL && arg_count < MAX_ARGS - 1) {
args[arg_count++] = token;
token = strtok(NULL, " \t\n");
}
args[arg_count] = NULL;
// Empty command
if (arg_count == 0)
return;
// Handle 'list' as a custom command
if (strcmp(args[0], "list") == 0) {
if (arg_count != 3) {
printf("Usage: list [f|n|i] <dirname>\n");
} else {
handle_list(args[1], args[2]);
}
return;
}
// Otherwise, fork and exec
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
} else if (pid == 0) {
// Child process
execvp(args[0], args);
perror("exec failed");
exit(EXIT_FAILURE);
} else {
// Parent process waits
wait(NULL);
} }
int main() {
char cmdline[MAX_CMD_LEN];
while (1) {
printf("myshell$ ");
if (fgets(cmdline, sizeof(cmdline), stdin) == NULL) {
break; // EOF
}
// Remove trailing newline
if (cmdline[strlen(cmdline) - 1] == '\n')
cmdline[strlen(cmdline) - 1] = '\0';
// Exit shell
if (strcmp(cmdline, "exit") == 0) {
break;
}
execute_command(cmdline);
}
return 0;
}
OUTPUT:
SET C:
1) Write a C program that behaves like a shell which displays the command
prompt ‘myshell$’. It accepts the command, tokenize the command line and
execute it by creating the child process. Also implement the additional
command ‘typeline’ as
myshell$ typeline n filename: It will display first n lines of the file.
myshell$ typeline -n filename: It will display last n lines of the file.
myshell$ typeline a filename: It will display all the lines of the file.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX_CMD_LEN 1024
#define MAX_ARGS 100
#define MAX_LINE_LEN 1024
#define MAX_LINES 1000
void typeline_first_n(int n, const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) {
perror("Unable to open file");
return;
}
char line[MAX_LINE_LEN];
int count = 0;
while (fgets(line, sizeof(line), file) && count < n) {
printf("%s", line);
count++;
}
fclose(file);
}
void typeline_last_n(int n, const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) {
perror("Unable to open file");
return;
}
char *lines[MAX_LINES];
int total = 0;
char buffer[MAX_LINE_LEN];
while (fgets(buffer, sizeof(buffer), file)) {
if (total < MAX_LINES) {
lines[total] = strdup(buffer); // Allocate and copy line
total++;
}
}
int start = (n >= total) ? 0 : total - n;
for (int i = start; i < total; i++) {
printf("%s", lines[i]);
free(lines[i]); // Free memory
}
fclose(file);
}
void typeline_all(const char *filename) {
FILE *file = fopen(filename, "r");
if (!file) {
perror("Unable to open file");
return;
}
char line[MAX_LINE_LEN];
while (fgets(line, sizeof(line), file)) {
printf("%s", line);
}
fclose(file);
}
void handle_typeline(char *option, char *filename) {
if (!option || !filename) {
printf("Usage:\n");
printf(" typeline n filename : Display first n lines\n");
printf(" typeline -n filename : Display last n lines\n");
printf(" typeline a filename : Display all lines\n");
return;
}
if (strcmp(option, "a") == 0) {
typeline_all(filename);
} else if (option[0] == '-' && strlen(option) > 1) {
int n = atoi(option + 1);
typeline_last_n(n, filename);
} else {
int n = atoi(option);
typeline_first_n(n, filename);
}
}
void execute_command(char *cmdline) {
char *args[MAX_ARGS];
char *token;
int arg_count = 0;
token = strtok(cmdline, " \t\n");
while (token != NULL && arg_count < MAX_ARGS - 1) {
args[arg_count++] = token;
token = strtok(NULL, " \t\n");
}
args[arg_count] = NULL;
if (arg_count == 0)
return;
// Custom command: typeline
if (strcmp(args[0], "typeline") == 0) {
if (arg_count != 3) {
printf("Invalid number of arguments for typeline.\n");
} else {
handle_typeline(args[1], args[2]);
}
return;
}
// Other commands - run normally
pid_t pid = fork();
if (pid < 0) {
perror("Fork failed");
} else if (pid == 0) {
execvp(args[0], args);
perror("Execution failed");
exit(EXIT_FAILURE);
} else {
wait(NULL);
} }
int main() {
char cmdline[MAX_CMD_LEN];
while (1) {
printf("myshell$ ");
if (fgets(cmdline, sizeof(cmdline), stdin) == NULL) {
break;
}
// Exit command
if (strcmp(cmdline, "exit\n") == 0) {
break;
}
execute_command(cmdline);
}
return 0;
}
OUTPUT:
2) Write a C program that behaves like a shell which displays the command
prompt ‘myshell$’. It accepts the command, tokenize the command line and
execute it by creating the child process. Also implement the additional
command ‘search’ as
myshell$ search f filename pattern : It will search the first occurrence of pattern
in the given file
myshell$ search a filename pattern : It will search all the occurrence of pattern
in the given file
myshell$ search c filename pattern : It will count the number of occurrence of
pattern in the given file
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX_CMD_LEN 1024
#define MAX_ARGS 100
#define MAX_LINE_LEN 1024
// Search first occurrence of pattern
void search_first(const char *filename, const char *pattern) {
FILE *file = fopen(filename, "r");
if (!file) {
perror("File open error");
return;
}
char line[MAX_LINE_LEN];
int line_num = 1;
while (fgets(line, sizeof(line), file)) {
if (strstr(line, pattern)) {
printf("First occurrence at line %d: %s", line_num, line);
fclose(file);
return;
}
line_num++;
}
printf("Pattern not found in file.\n");
fclose(file);
}
// Search all occurrences of pattern
void search_all(const char *filename, const char *pattern) {
FILE *file = fopen(filename, "r");
if (!file) {
perror("File open error");
return;
}
char line[MAX_LINE_LEN];
int line_num = 1;
int found = 0;
while (fgets(line, sizeof(line), file)) {
if (strstr(line, pattern)) {
printf("Line %d: %s", line_num, line);
found = 1;
}
line_num++;
}
if (!found) {
printf("Pattern not found in file.\n");
}
fclose(file);
}
// Count occurrences of pattern
void search_count(const char *filename, const char *pattern) {
FILE *file = fopen(filename, "r");
if (!file) {
perror("File open error");
return;
}
char line[MAX_LINE_LEN];
int count = 0;
while (fgets(line, sizeof(line), file)) {
char *ptr = line;
while ((ptr = strstr(ptr, pattern)) != NULL) {
count++;
ptr += strlen(pattern); // Move past the last match
} }
printf("Total occurrences of '%s': %d\n", pattern, count);
fclose(file);
}
// Handle 'search' command
void handle_search(char *mode, char *filename, char *pattern) {
if (!mode || !filename || !pattern) {
printf("Usage: search [f|a|c] filename pattern\n");
return;
}
if (strcmp(mode, "f") == 0) {
search_first(filename, pattern);
} else if (strcmp(mode, "a") == 0) {
search_all(filename, pattern);
} else if (strcmp(mode, "c") == 0) {
search_count(filename, pattern);
} else {
printf("Invalid mode. Use: f (first), a (all), c (count)\n");
}
}
// Tokenize and execute command
void execute_command(char *cmdline) {
char *args[MAX_ARGS];
int arg_count = 0;
char *token = strtok(cmdline, " \t\n");
while (token != NULL && arg_count < MAX_ARGS - 1) {
args[arg_count++] = token;
token = strtok(NULL, " \t\n");
}
args[arg_count] = NULL;
if (arg_count == 0)
return;
// Handle custom command: search
if (strcmp(args[0], "search") == 0) {
if (arg_count != 4) {
printf("Usage: search [f|a|c] filename pattern\n");
} else {
handle_search(args[1], args[2], args[3]);
}
return;
}
// Handle regular shell commands
pid_t pid = fork();
if (pid < 0) {
perror("Fork failed");
} else if (pid == 0) {
execvp(args[0], args);
perror("Execution failed");
exit(EXIT_FAILURE);
} else {
wait(NULL);
}
}
int main() {
char cmdline[MAX_CMD_LEN];
while (1) {
printf("myshell$ ");
if (fgets(cmdline, sizeof(cmdline), stdin) == NULL) {
break;
}
if (strcmp(cmdline, "exit\n") == 0) {
break;
}
execute_command(cmdline);
}
return 0;
}
OUTPUT: