#include "sish.h"
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <libgen.h>
#include <pwd.h>
#include <sched.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "builtins.h"
#include "cmd_exec.h"
#include "utils.h"
volatile sig_atomic_t interrupted = false;
/* special values */
pid_t last_pid_bg = 0;
int last_fg_exit_status = 0;
/* cli flags */
bool flag_tracing_enabled = false;
bool flag_command_specified = false;
int
shell_loop(int argc, char** argv)
{
/* block Control + C, Z, \ (Int, tstop, quit)*/
ignore_signals();
while (true)
{
interrupted = false;
if (!flag_command_specified)
{
/* output would otherwise appear after the command executed due to
* exit handlers flushing stdio buffers, so it needs to explicitly
* be prevented */
printf("%s ", SHELL_NAME);
}
char* token_args[MAX_ARGS] = {0};
int token_args_count = 0;
char user_raw_input[BUFSIZ] = {0};
if (flag_command_specified)
{
/* ./sish [flags] <cmd> - start at first non-option to accomdate
* both -x -c and -xc */
for (int i = optind - 1; i < argc; i++)
{
strncat(user_raw_input, argv[i],
sizeof(user_raw_input) - strlen(user_raw_input) - 1);
if (i < argc - 1)
{
strncat(user_raw_input, " ",
sizeof(user_raw_input) - strlen(user_raw_input) -
1);
}
}
}
else if (fgets(user_raw_input, sizeof(user_raw_input), stdin) == NULL)
{
/* supresses "[...] fgets: Interrupted system call." */
if (!interrupted)
{
/* EOF was sent */
if (feof(stdin))
{
printf("\n");
exit(EXIT_SUCCESS);
}
fprintf(stderr, "%s: fgets: %s.\n", GET_PROGNAME_ERR,
strerror(errno));
}
/* man page dictates this is necessary when testing EOF */
clearerr(stdin);
continue;
}
if ((token_args_count = tokenize(user_raw_input, token_args)) == -1)
{
/* error message handled in the call above */
continue;
}
try_expand_env_vars(token_args);
run_commands(token_args);
for (int i = 0; i < token_args_count; i++)
{
free(token_args[i]);
}
if (flag_command_specified)
{
exit(EXIT_SUCCESS);
}
}
}
int
main(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "xc:")) != -1)
{
switch (opt)
{
case 'x':
flag_tracing_enabled = true;
break;
case 'c':
flag_command_specified = true;
break;
default:
fprintf(stderr, "Usage: %s [-x] [-c command]\n", GET_PROGNAME_ERR);
exit(EXIT_FAILURE);
}
}
set_shell_env(argv[0]);
return shell_loop(argc, argv);
}