Skip to content
Permalink
Browse files

Update Eval() to evaluate the command line that the user has just typ…

…ed in
  • Loading branch information
heapsmash committed Oct 9, 2019
1 parent d0428a5 commit bb3d92453e8461d133ac8e808860c40e026457a2
Showing with 116 additions and 49 deletions.
  1. +116 −49 tsh.c
165 tsh.c
@@ -1,3 +1,5 @@
#pragma clang diagnostic push
#pragma ide diagnostic ignored "readability-redundant-control-flow"
/*
* tsh - A tiny shell program with job control
*
@@ -71,31 +73,33 @@ void sigchld_handler(int sig);
void sigtstp_handler(int sig);
void sigint_handler(int sig);

/* Here are helper routines that we've provided for you */
int parseline(const char *cmdline, char **argv);
void sigquit_handler(int sig);

void clearjob(struct job_t *job);
void initjobs(struct job_t *jobs);
int maxjid(struct job_t *jobs);
int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline);
int deletejob(struct job_t *jobs, pid_t pid);
pid_t fgpid(struct job_t *jobs);
struct job_t *getjobpid(struct job_t *jobs, pid_t pid);
struct job_t *getjobjid(struct job_t *jobs, int jid);
void clearjob(struct job_t *structjob);
void initjobs(struct job_t *structjob);
int maxjid(struct job_t *structjob);
int addjob(struct job_t *structjob, pid_t pid, int state, char *cmdline);
int deletejob(struct job_t *structjob, pid_t pid);
pid_t fgpid(struct job_t *structjob);
struct job_t *getjobpid(struct job_t *structjob, pid_t pid);
struct job_t *getjobjid(struct job_t *structjob, int jid);
int pid2jid(pid_t pid);
void listjobs(struct job_t *jobs);
void listjobs(struct job_t *structjob);

void usage(void);
void unix_error(char *msg);
void app_error(char *msg);
typedef void handler_t(int);
handler_t *Signal(int signum, handler_t *handler);

pid_t Fork(void);


/*
* main - The shell's main routine
*/

int main(int argc, char **argv)
{
char c;
@@ -172,8 +176,36 @@ int main(int argc, char **argv)
* background children don't receive SIGINT (SIGTSTP) from the kernel
* when we type ctrl-c (ctrl-z) at the keyboard.
*/

void eval(char *cmdline)
{
char *argv[MAXARGS]; /* argument list execve() */
char buf[MAXLINE]; /* Holds the modified command line */
int bg; /* Should the job run in the bg or fg */
pid_t pid; /* process id */

strcpy(buf, cmdline);
bg = parseline(buf, argv);

if (argv[0] == NULL)
return;

if (!builtin_cmd(argv)) {
if ((pid = Fork()) == 0) {
if (execve(argv[0], argv, environ) < 0) {
printf("%s: Command not found.\n", argv[0]);
exit(0);
}
}

if (!bg) {
int status;
if (waitpid(pid, &status, 0) < 0)
unix_error("waitfg: waitpid error");
} else
printf("%d %s", pid, cmdline);
}

return;
}

@@ -183,8 +215,9 @@ void eval(char *cmdline)
*
* Characters enclosed in single quotes are treated as a single
* argument. Return true if the user has requested a BG job, false if
* the user has requested a FG job.
* the user has requested a FG job.
*/

int parseline(const char *cmdline, char **argv)
{
static char array[MAXLINE]; /* holds local copy of command line */
@@ -238,6 +271,7 @@ int parseline(const char *cmdline, char **argv)
* builtin_cmd - If the user has typed a built-in command then execute
* it immediately.
*/

int builtin_cmd(char **argv)
{
return 0; /* not a builtin command */
@@ -247,6 +281,7 @@ int builtin_cmd(char **argv)
/*
* do_bgfg - Execute the builtin bg and fg commands
*/

void do_bgfg(char **argv)
{
return;
@@ -256,6 +291,7 @@ void do_bgfg(char **argv)
/*
* waitfg - Block until process pid is no longer the foreground process
*/

void waitfg(pid_t pid)
{
return;
@@ -272,6 +308,7 @@ void waitfg(pid_t pid)
* available zombie children, but doesn't wait for any other
* currently running children to terminate.
*/

void sigchld_handler(int sig)
{
return;
@@ -294,6 +331,7 @@ void sigint_handler(int sig)
* the user types ctrl-z at the keyboard. Catch it and suspend the
* foreground job by sending it a SIGTSTP.
*/

void sigtstp_handler(int sig)
{
return;
@@ -308,76 +346,81 @@ void sigtstp_handler(int sig)
**********************************************/

/* clearjob - Clear the entries in a job struct */
void clearjob(struct job_t *job)

void clearjob(struct job_t *structjob)
{
job->pid = 0;
job->jid = 0;
job->state = UNDEF;
job->cmdline[0] = '\0';
structjob->pid = 0;
structjob->jid = 0;
structjob->state = UNDEF;
structjob->cmdline[0] = '\0';
}


/* initjobs - Initialize the job list */
void initjobs(struct job_t *jobs)

void initjobs(struct job_t *structjob)
{
int i;

for (i = 0; i < MAXJOBS; i++)
clearjob(&jobs[i]);
clearjob(&structjob[i]);
}


/* maxjid - Returns largest allocated job ID */
int maxjid(struct job_t *jobs)

int maxjid(struct job_t *structjob)
{
int i, max = 0;

for (i = 0; i < MAXJOBS; i++)
if (jobs[i].jid > max)
max = jobs[i].jid;
if (structjob[i].jid > max)
max = structjob[i].jid;
return max;
}


/* addjob - Add a job to the job list */
int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline)

int addjob(struct job_t *structjob, pid_t pid, int state, char *cmdline)
{
int i;

if (pid < 1)
return 0;

for (i = 0; i < MAXJOBS; i++) {
if (jobs[i].pid == 0) {
jobs[i].pid = pid;
jobs[i].state = state;
jobs[i].jid = nextjid++;
if (structjob[i].pid == 0) {
structjob[i].pid = pid;
structjob[i].state = state;
structjob[i].jid = nextjid++;
if (nextjid > MAXJOBS)
nextjid = 1;
strcpy(jobs[i].cmdline, cmdline);
strcpy(structjob[i].cmdline, cmdline);
if (verbose) {
printf("Added job [%d] %d %s\n", jobs[i].jid, jobs[i].pid, jobs[i].cmdline);
printf("Added job [%d] %d %s\n", structjob[i].jid, structjob[i].pid, structjob[i].cmdline);
}
return 1;
}
}
printf("Tried to create too many jobs\n");
printf("Tried to create too many structjob\n");
return 0;
}


/* deletejob - Delete a job whose PID=pid from the job list */
int deletejob(struct job_t *jobs, pid_t pid)

int deletejob(struct job_t *structjob, pid_t pid)
{
int i;

if (pid < 1)
return 0;

for (i = 0; i < MAXJOBS; i++) {
if (jobs[i].pid == pid) {
clearjob(&jobs[i]);
nextjid = maxjid(jobs) + 1;
if (structjob[i].pid == pid) {
clearjob(&structjob[i]);
nextjid = maxjid(structjob) + 1;
return 1;
}
}
@@ -386,46 +429,50 @@ int deletejob(struct job_t *jobs, pid_t pid)


/* fgpid - Return PID of current foreground job, 0 if no such job */
pid_t fgpid(struct job_t *jobs)

pid_t fgpid(struct job_t *structjob)
{
int i;

for (i = 0; i < MAXJOBS; i++)
if (jobs[i].state == FG)
return jobs[i].pid;
if (structjob[i].state == FG)
return structjob[i].pid;
return 0;
}


/* getjobpid - Find a job (by PID) on the job list */
struct job_t *getjobpid(struct job_t *jobs, pid_t pid)

struct job_t *getjobpid(struct job_t *structjob, pid_t pid)
{
int i;

if (pid < 1)
return NULL;
for (i = 0; i < MAXJOBS; i++)
if (jobs[i].pid == pid)
return &jobs[i];
if (structjob[i].pid == pid)
return &structjob[i];
return NULL;
}


/* getjobjid - Find a job (by JID) on the job list */
struct job_t *getjobjid(struct job_t *jobs, int jid)

struct job_t *getjobjid(struct job_t *structjob, int jid)
{
int i;

if (jid < 1)
return NULL;
for (i = 0; i < MAXJOBS; i++)
if (jobs[i].jid == jid)
return &jobs[i];
if (structjob[i].jid == jid)
return &structjob[i];
return NULL;
}


/* pid2jid - Map process ID to job ID */

int pid2jid(pid_t pid)
{
int i;
@@ -441,14 +488,15 @@ int pid2jid(pid_t pid)


/* listjobs - Print the job list */
void listjobs(struct job_t *jobs)

void listjobs(struct job_t *structjob)
{
int i;

for (i = 0; i < MAXJOBS; i++) {
if (jobs[i].pid != 0) {
printf("[%d] (%d) ", jobs[i].jid, jobs[i].pid);
switch (jobs[i].state) {
if (structjob[i].pid != 0) {
printf("[%d] (%d) ", structjob[i].jid, structjob[i].pid);
switch (structjob[i].state) {
case BG:
printf("Running ");
break;
@@ -459,9 +507,9 @@ void listjobs(struct job_t *jobs)
printf("Stopped ");
break;
default:
printf("listjobs: Internal error: job[%d].state=%d ", i, jobs[i].state);
printf("listjobs: Internal error: job[%d].state=%d ", i, structjob[i].state);
}
printf("%s", jobs[i].cmdline);
printf("%s", structjob[i].cmdline);
}
}
}
@@ -477,6 +525,7 @@ void listjobs(struct job_t *jobs)
/*
* usage - print a help message
*/

void usage(void)
{
printf("Usage: shell [-hvp]\n");
@@ -490,6 +539,7 @@ void usage(void)
/*
* unix_error - unix-style error routine
*/

void unix_error(char *msg)
{
fprintf(stdout, "%s: %s\n", msg, strerror(errno));
@@ -500,6 +550,7 @@ void unix_error(char *msg)
/*
* app_error - application-style error routine
*/

void app_error(char *msg)
{
fprintf(stdout, "%s\n", msg);
@@ -510,6 +561,7 @@ void app_error(char *msg)
/*
* Signal - wrapper for the sigaction function
*/

handler_t *Signal(int signum, handler_t *handler)
{
struct sigaction action, old_action;
@@ -528,11 +580,26 @@ handler_t *Signal(int signum, handler_t *handler)
* sigquit_handler - The driver program can gracefully terminate the
* child shell by sending it a SIGQUIT signal.
*/

void sigquit_handler(int sig)
{
printf("Terminating after receipt of SIGQUIT signal\n");
exit(1);
}


#pragma clang diagnostic pop
/*
* Wrapper for fork.
*/

pid_t Fork(void)
{
pid_t pid;

if ((pid = fork()) < 0)
unix_error("Fork error");
return pid;
}


#pragma clang diagnostic pop

0 comments on commit bb3d924

Please sign in to comment.
You can’t perform that action at this time.