I have come up with a code for a simple shell in C (with some help from ChatGPT).
However, for the first part of my endless list of to-dos, I can't make my shell give me the same error code as echo "qwerty" | /bin/sh
which is /bin/sh: 1: qwerty not found
Something to do with my execute_command()
function but can't figure it out on my own.
After compilation, my shell should have error message like ./hsh: 1: qwerty: not found
So far, I have been able to print out ...qwerty: not found
but not the name of the custom shell or the line number.
#define SHELL_H
#define MAX_NUM_ARGS 10
/* Standard Headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
/* Function Prototypes */
void parse_command(char *command, char *args[]);
void execute_command(char *args[]);
#endif /* #ifndef SHELL_H */
void execute_command(char *args[])
{
int status;
pid_t pid;
pid_t ppid = getppid();
char cmd[100], shell[100];
FILE *fp;
snprintf(cmd, sizeof(cmd), "ps -p %d -o comm=", ppid);
fp = popen(cmd, "r");
if (fp == NULL)
perror("Failed to execute command\n");
if (fgets(shell, sizeof(shell), fp) == NULL)
perror("Failed to read output\n");
pclose(fp);
pid = fork();
if (pid == 0)
{
execvp(args[0], args);
printf("%s: %d: %s: not found\n", shell, __LINE__, args[0]);
exit(1);
}
else if (pid > 0)
{
wait(&status);
}
else
{
perror("Error: failed to fork\n");
exit(1);
}
}
void parse_command(char *command, char *args[])
{
char *token = strtok(command, " ");
int i = 0;
while (token != NULL && i < MAX_NUM_ARGS)
{
args[i] = token;
token = strtok(NULL, " ");
i++;
}
args[i] = NULL;
}
int main(void)
{
char *command = NULL;
size_t n = 0;
char *args[MAX_NUM_ARGS + 1];
/*
* function isatty() is used to check if input is
* coming from a pipe or the terminal. Read man isatty()
*/
if (!isatty(STDIN_FILENO))
{
if (getline(&command, &n, stdin) == -1)
{
perror("Error: getline() failed\n");
return (1);
}
command[strcspn(command, "\n")] = '\0';
parse_command(command, args);
execute_command(args);
free(command);
return (0);
}
while (1)
{
printf(">> ");
if (getline(&command, &n, stdin) == -1)
{
perror("Error: getline() failed\n");
break;
}
command[strcspn(command, "\n")] = '\0';
parse_command(command, args);
if (strcmp(args[0], "exit") == 0)
{
break;
}
execute_command(args);
}
free(command);
return (0);
}