I need help with my project it\'s about creating a simple shell in c (ubuntu) wi
ID: 3859095 • Letter: I
Question
I need help with my project
it's about creating a simple shell in c (ubuntu) with history feature
thanks to some people here :) I made the code but there is a tiny little problem :(
when I type "ls -a &" in terminal it didn't work properly, it should show something like this ([1] 7525) for example
but no it didn't :(
======= this is the code ========
/*
* warda Almutairi
* Ghadeer
* Fatma Alazmy
*Reem
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <limits.h>
#include <errno.h>
static char * cmd_history[10];
static int cmd_history_count = 0;
static void exec_cmd(const char * line)
{
char * CMD = strdup(line);
char *params[10];
int argc = 0;
int i;
params[argc++] = strtok(CMD, " ");
while(params[argc-1] != NULL){
params[argc++] = strtok(NULL, " ");
}
argc--;
int background = 0;
if(strcmp(args[0], "exit") == 0)
break;
if(strcmp(params[argc-1], "&") == 0)
{
/*from the book example*/
pid_t pid;
pid = fork();
if (pid < 0)
{
fprintf(stderr, "Fork failed ");
return;
}
else if (pid == 0)
{
execvp(argc[0], argc);
for(int j=0;j<i;j++)
argc[j] = NULL;
}
else
{
wait(NULL);
}
}
else
{
background = 1;
params[--argc] = NULL;
}
int fd[2] = {-1, -1};
while(argc >= 3)
{
if(strcmp(params[argc-2], ">") == 0){
fd[1] = open(params[argc-1], O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP|S_IWGRP);
if(fd[1] == -1){
perror("open");
free(CMD);
return;
}
params[argc-2] = NULL;
argc -= 2;
}
else if(strcmp(params[argc-2], "<") == 0)
{
fd[0] = open(params[argc-1], O_RDONLY);
if(fd[0] == -1)
{
perror("open");
free(CMD);
return;
}
params[argc-2] = NULL;
argc -= 2;
}
else
{
break;
}
}
int status;
pid_t pid = fork();
switch(pid)
{
case -1:
perror("fork");
break;
case 0:
if(fd[0] != -1)
{
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
{
perror("dup2");
exit(1);
}
}
if(fd[1] != -1)
{
if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
{
perror("dup2");
exit(1);
}
}
execvp(params[0], params);
perror("execvp");
exit(0);
default: // parent
close(fd[0]);close(fd[1]);
if(!background)
waitpid(pid, &status, 0);
break;
}
free(CMD);
}
static void add_to_history(const char * cmd)
{
if(cmd_history_count == (10-1))
{
int i;
free(cmd_history[0]);
for(i=1; i < cmd_history_count; i++)
cmd_history[i-1] = cmd_history[i];
cmd_history_count--;
}
cmd_history[cmd_history_count++] = strdup(cmd);
}
static void run_from_history(const char * cmd)
{
int index = 0;
if(cmd_history_count == 0)
{
printf("No commands in history ");
return ;
}
if(cmd[1] == '!')
index = cmd_history_count-1;
else
{
index = atoi(&cmd[1]) - 1;
if((index < 0) || (index > cmd_history_count))
{
fprintf(stderr, "No such command in history. ");
return;
}
}
printf("%s ", cmd);
exec_cmd(cmd_history[index]);
}
static void list_history()
{
int i;
for(i=cmd_history_count-1; i >=0 ; i--)
{
printf("%i %s ", i+1, cmd_history[i]);
}
}
static void signal_handler(const int rc)
{
switch(rc)
{
case SIGTERM:
case SIGINT:
break;
case SIGCHLD:
while (waitpid(-1, NULL, WNOHANG) > 0);
break;
}
}
int main(int argc, char *argv[])
{
struct sigaction act, act_old;
act.sa_handler = signal_handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
if( (sigaction(SIGINT, &act, &act_old) == -1) || (sigaction(SIGCHLD, &act, &act_old) == -1))
{
perror("signal");
return 1;
}
size_t line_size = 80;
char * line = (char*) malloc(sizeof(char)*line_size);
if(line == NULL)
{
perror("malloc");
return 1;
}
int inter = 0;
while(1)
{
if(!inter)
printf("OSH> ");
if(getline(&line, &line_size, stdin) == -1)
{
if(errno == EINTR)
{
clearerr(stdin);
inter = 1;
continue;
}
perror("getline");
break;
}
inter = 0;
int line_len = strlen(line);
if(line_len == 1)
{
continue;
}
line[line_len-1] = '';
if(strcmp(line, "exit") == 0)
{
break;
}
else if(strcmp(line, "history") == 0)
{
list_history();
}
else if(line[0] == '!')
{
run_from_history(line);
}
else
{
add_to_history(line);
exec_cmd(line);
}
}
free(line);
return 0;
}
---------------------------------------------------
please help :(, this is the last part of my project and I'm strugling with it
Explanation / Answer
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <limits.h>
#include <errno.h>
static char * cmd_history[10];
static int cmd_history_count = 0;
static void exec_cmd(const char * line)
{
char * CMD = strdup(line);
char *params[10];
int argc = 0;
int i;
params[argc++] = strtok(CMD, " ");
while(params[argc-1] != NULL){
params[argc++] = strtok(NULL, " ");
}
argc--;
int background = 0;
if(strcmp(args[0], "exit") == 0)
break;
if(strcmp(params[argc-1], "&") == 0)
{
/*from the book example*/
pid_t pid;
pid = fork();
if (pid < 0)
{
fprintf(stderr, "Fork failed ");
return;
}
else if (pid == 0)
{
execvp(argc[0], argc);
for(int j=0;j<i;j++)
argc[j] = NULL;
}
else
{
wait(NULL);
}
}
else
{
background = 1;
params[--argc] = NULL;
}
int fd[2] = {-1, -1};
while(argc >= 3)
{
if(strcmp(params[argc-2], ">") == 0){
fd[1] = open(params[argc-1], O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP|S_IWGRP);
if(fd[1] == -1){
perror("open");
free(CMD);
return;
}
params[argc-2] = NULL;
argc -= 2;
}
else if(strcmp(params[argc-2], "<") == 0)
{
fd[0] = open(params[argc-1], O_RDONLY);
if(fd[0] == -1)
{
perror("open");
free(CMD);
return;
}
params[argc-2] = NULL;
argc -= 2;
}
else
{
break;
}
}
int status;
pid_t pid = fork();
switch(pid)
{
case -1:
perror("fork");
break;
case 0:
if(fd[0] != -1)
{
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
{
perror("dup2");
exit(1);
}
}
if(fd[1] != -1)
{
if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
{
perror("dup2");
exit(1);
}
}
execvp(params[0], params);
perror("execvp");
exit(0);
default: // parent
close(fd[0]);close(fd[1]);
if(!background)
waitpid(pid, &status, 0);
break;
}
free(CMD);
}
static void add_to_history(const char * cmd)
{
if(cmd_history_count == (10-1))
{
int i;
free(cmd_history[0]);
for(i=1; i < cmd_history_count; i++)
cmd_history[i-1] = cmd_history[i];
cmd_history_count--;
}
cmd_history[cmd_history_count++] = strdup(cmd);
}
static void run_from_history(const char * cmd)
{
int index = 0;
if(cmd_history_count == 0)
{
printf("No commands in history ");
return ;
}
if(cmd[1] == '!')
index = cmd_history_count-1;
else
{
index = atoi(&cmd[1]) - 1;
if((index < 0) || (index > cmd_history_count))
{
fprintf(stderr, "No such command in history. ");
return;
}
}
printf("%s ", cmd);
exec_cmd(cmd_history[index]);
}
static void list_history()
{
int i;
for(i=cmd_history_count-1; i >=0 ; i--)
{
printf("%i %s ", i+1, cmd_history[i]);
}
}
static void signal_handler(const int rc)
{
switch(rc)
{
case SIGTERM:
case SIGINT:
break;
case SIGCHLD:
while (waitpid(-1, NULL, WNOHANG) > 0);
break;
}
}
int main(int argc, char *argv[])
{
struct sigaction act, act_old;
act.sa_handler = signal_handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
if( (sigaction(SIGINT, &act, &act_old) == -1) || (sigaction(SIGCHLD, &act, &act_old) == -1))
{
perror("signal");
return 1;
}
size_t line_size = 80;
char * line = (char*) malloc(sizeof(char)*line_size);
if(line == NULL)
{
perror("malloc");
return 1;
}
int inter = 0;
while(1)
{
if(!inter)
printf("OSH> ");
if(getline(&line, &line_size, stdin) == -1)
{
if(errno == EINTR)
{
clearerr(stdin);
inter = 1;
continue;
}
perror("getline");
break;
}
inter = 0;
int line_len = strlen(line);
if(line_len == 1)
{
continue;
}
line[line_len-1] = '';
if(strcmp(line, "exit") == 0)
{
break;
}
else if(strcmp(line, "history") == 0)
{
list_history();
}
else if(line[0] == '!')
{
run_from_history(line);
}
else
{
add_to_history(line);
exec_cmd(line);
}
}
free(line);
return 0;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.