Skip to content

Instantly share code, notes, and snippets.

@ggreenleaf
Created October 7, 2014 01:16
Show Gist options
  • Select an option

  • Save ggreenleaf/9c8c0bc50d656336c7be to your computer and use it in GitHub Desktop.

Select an option

Save ggreenleaf/9c8c0bc50d656336c7be to your computer and use it in GitHub Desktop.
//Assingment 2 shell
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#define ERRFORK printf("ERROR: fork faild\n");
#define ERREXEC printf("ERROR: exec failed\n");
//prototypes
void parsecmd(char*, char**); //parse command into array of arguments
void clearargv(char**);
_Bool opcmp(const char*);
void parseargvs(const char**, char**, char**);
void execute(char**); //run command
void execpipe(char**);
void execapp (char**);
void execin (char**);
void execout (char**);
const int ARGC = 64;
int main()
{
char line[256];
char prompt[] = "grsh$ ";
char *argv[64]; //cmd line arguments
//3d array of arguments
//arg[1] - |> > >> null if one command
//arg[2] - first command of redirect/ IO
//arg[3] - seccond command
/* spit out the prompt */
// /* Try getting input. If error or EOF, exit */
while( 1 )
{
/* fgets leaves '\n' in input buffer. ditch it */
printf("%s",prompt);
fgets(line, sizeof line, stdin);
line[strlen(line)-1] = '\0';
// This is where I take the easy route.
// system(line);
// fork(), execvp() & co. go here in your version
if (strstr(line,">>"))
{
parsecmd(line, argv);
execapp(argv);
}
else if (strstr(line,">"))
{
parsecmd(line, argv);
execout(argv);
}
else if (strstr(line,"<"))
{
parsecmd(line, argv);
execin(argv);
}
else if (strstr(line,"|"))
{
parsecmd(line, argv);
execpipe(argv);
}
else
{
parsecmd(line,argv);
if (strcmp(argv[0],"list") == 0)
argv[0] = "ls"; //change first argument to ls command
else if (strcmp(argv[0],"exit") == 0 )
exit(0);
execute(argv);
}
clearargv(argv);
}
return 0;
}
//taken from csl.mtu.edu
void parsecmd(char *line, char **argv)
{
while (*line != '\0') /* if not the end of line ....... */
{
while (*line == ' ' || *line == '\t' || *line == '\n')
*line++ = '\0'; /* replace white spaces with 0 */
*argv++ = line; /* save the argument position */
while (*line != '\0' && *line != ' ' &&
*line != '\t' && *line != '\n')
line++; /* skip the argument until ... */
}
*argv = '\0'; /* mark the end of argument list */
}
void clearargv(char **argv)
{
for (int i = 0; i < ARGC; i++) //not good
{
argv[i] = NULL;
}
}
void execute(char **argv)
{
pid_t pid;
pid = fork();
if (pid < 0 ) //fork a child process
{
ERRFORK
exit(1);
}
else if (pid == 0 )
{
if (execvp(*argv,argv) < 0 )
{
ERREXEC
exit(1);
}
}
else
{
wait(NULL);
}
}
void execpipe (char **argv)
{
char *cmdArgv1[10];
char *cmdArgv2[10];
parseargvs(argv,cmdArgv1,cmdArgv2);
int pfd[2];
pid_t pid, pid2;
pid2 = fork();
if ( pid2 == 0 )
{
pipe(pfd);
pid = fork();
if (pid < 0)
{
ERRFORK
exit(1);
}
else if (pid == 0)
{
close(pfd[1]);
dup2(pfd[0],0);
close(pfd[0]);
execvp(cmdArgv2[0],cmdArgv2);
}
else
{
close(pfd[0]);
dup2(pfd[1],1);
close(pfd[1]);
execvp(cmdArgv1[0],cmdArgv1);
}
}
else
{
wait(NULL);
wait(NULL);
}
}
// execute input file
//ex less < grsh.c
void execin (char **argv)
{
char *cmdArgv1[10];
char *cmdArgv2[10]; //input will only be 0
parseargvs(argv,cmdArgv1,cmdArgv2);
int pid = fork();
if (pid < 0 )
{
ERRFORK
exit(1);
}
else if ( pid == 0)
{
int in;
in = open(cmdArgv2[0], O_RDONLY);
dup2(in,0); //replace stdin with file input
close(in);
if (execvp(*cmdArgv1,cmdArgv1) < 0)
{
ERREXEC
exit(1);
}
}
else
wait(NULL);
}
void execout (char **argv)
{
char *cmdArgv1[10];
char *cmdArgv2[10]; //input will only be 0
parseargvs(argv,cmdArgv1,cmdArgv2);
int pid = fork();
if (pid < 0 )
{
ERRFORK
exit(1);
}
else if ( pid == 0)
{
int out;
out = open(cmdArgv2[0], O_WRONLY | O_TRUNC | O_CREAT, 0700);
dup2(out,1); //replace stdout with output file
close(out);
if (execvp(*cmdArgv1,cmdArgv1) < 0)
{
ERREXEC
exit(1);
}
}
else
wait(NULL);
}
void execapp (char **argv)
{
char *cmdArgv1[10];
char *cmdArgv2[10]; //input will only be 0
parseargvs(argv,cmdArgv1,cmdArgv2);
int pid = fork();
if (pid < 0 )
{
ERRFORK
exit(1);
}
else if ( pid == 0)
{
int out;
out = open(cmdArgv2[0], O_WRONLY | O_APPEND | O_CREAT, 0700);
dup2(out,1); //replace stdout with output file
close(out);
if (execvp(*cmdArgv1,cmdArgv1) < 0)
{
ERREXEC
exit(1);
}
}
else
wait(NULL);
}
// compares string and returns true if | > >> < else false
_Bool opcmp(const char* str)
{
return (strcmp(">>",str) == 0 || strcmp(">",str) == 0
|| strcmp("<",str) == 0 || strcmp("|", str) == 0 );
}
//copies arguments from argv into cmdArgv1
// if | < > >> is in argument move next args to cmdArgv2
void parseargvs(const char **argv, char **cmdArgv1, char **cmdArgv2)
{
int i = 0;
while (!opcmp(argv[i]))
{
cmdArgv1[i] = argv[i];
i++;
}
cmdArgv1[i] = '\0';
i++;
int j = 0;
while (argv[i] != '\0')
{
cmdArgv2[j] = argv[i];
i++; j++;
}
}
//Assingment 2 shell
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment