Unix Minishell
Unix Minishell
h>
#include <stdio.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include<fcntl.h>
#include<signal.h>
#include<malloc.h>
#include<stdlib.h>
struct job{
struct job* next;
int jobno; /* our own job control no..starts from 1
*/
pid_t processgroup; /* process id of the main process made into group id
*/
int bg; /* set 1 true if process is bg
*/
int status; /*running=1,stopped=2,needsterminal=3,finished=4,terminate
d=5*/
int filein; /* if stdin and stdout are redirected .
*/
int fileout;
char infilename[20];
char outfilename[20];
char jobname[20];
pid_t pid;
struct termios tmodes;
};
int gjobno;
pid_t shellPid;
pid_t shellPgid;
int volatile run;
struct job *joblist;
char* argv[20];
int argc;
char* charBuffer;
/*takes commands from stdin and parses into an array and keeps the count in argc
*/
struct termios shell_tmodes;
int shell_terminal;
int shell_is_interactive;
void processInput();
struct job * find_job (pid_t pid)
{
struct job *j;
for (j = joblist; j; j = j->next)
if (j->pid == pid)
return j;
return NULL;
}
/*creats a job in response to parameters passed from processInput(),
* specifically initialise the FILEIN/OUT Bg,jobno,jobstatus jobname
* (Note: next,processgoup,tmodes has to be set by after forking)*/
struct job* creatjob(char * pjobname, int ptmpin,int ptmpout,int pbg,char* pinfi
lename,char* poutfilename){
struct job* tmp = (struct job*)malloc(sizeof(struct job));
tmp->next=NULL;
tmp->jobno=gjobno;
tmp->bg=pbg;
tmp->filein=ptmpin;
tmp->fileout=ptmpout;
tmp->status=1;
strcpy(tmp->infilename,pinfilename);
strcpy(tmp->outfilename,poutfilename);
tmp->processgroup=0;
tmp->pid=0;
tcgetattr(shell_terminal, &tmp->tmodes);
strcpy(tmp->jobname,pjobname);
if(joblist!=NULL){tmp->next=joblist;joblist =tmp;}
else joblist =tmp;
gjobno++;
return tmp;
}
/* Make sure the shell is running interactively as the foreground job
before proceeding. */
void init_shell() {
run = 1;
gjobno = 1;
shellPid = getpid();
joblist = NULL;
/* See if we are running interactively. */
shell_terminal = STDIN_FILENO;
shell_is_interactive = isatty(shell_terminal);
if (shell_is_interactive) {
/* Loop until we are in the foreground. */
while (tcgetpgrp(shell_terminal) != (shellPgid = getpgrp()))
kill(-shellPgid, SIGTTIN);
/* Ignore interactive and job-control signals. */
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
//signal(SIGCHLD, SIG_IGN);
/* Put ourselves in our own process group. */
shellPgid = getpid();
if (setpgid(shellPgid, shellPgid) < 0) {
perror("Couldn't put the shell in its own process group");
exit(1);
}
/* Grab control of the terminal. */
tcsetpgrp(shell_terminal, shellPgid);
/* Save default terminal attributes for shell. */
tcgetattr(shell_terminal, &shell_tmodes);
}
}
/*main of the program. set up initial globals and call prompt() to wait for resp
onse. then process user input() */
int main(){
init_shell();
while (run == 1) {
waitchild(0);
//if the shell is not in fg then there must be a fg job
// we wait till control has return to shell
while(tcgetpgrp(shell_terminal)!=shellPgid){
waitchild(0);
}
printf("\n:~)");
//wait till currant fg job exits.
//poll stdin
int peekstdin=0;
while((peekstdin=fgetc(stdin))==0&&run==1){
//wait for child process
}
ungetc(peekstdin,stdin);
//process commands
prompt();
}
}