rendered paste bodyi want to know how it works...is it doing a system calls
// shell.c
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#define PROMPT "MyShell"
#define FALSE 0
#define TRUE 1
#define NORMALMODE 0
#define CONCURRENTMODE 1
#define STDIN 0
#define STDOUT 1
#define DEFAULT 2
// structure to hold the command name and arguments
typedef struct command_t
{
char *name;
int argc;
char **argv;
} CommandType;
// declaration of functions used in program
char* getCommandPath(char* command);
void trim(char* name);
int runCommand(CommandType* command);
int runConcurrentCommand(CommandType* command);
int runPipedCommands(CommandType* command, CommandType* command2);
int runRedirectedCommand(CommandType* command, char* file, int fileid);
char *path;
char *ptr;
char *input;
int pid;
int status;
int redirectionType;
// returns the full path of a command
// returns NULL if the command is not found on the path
char* getCommandPath(char* command)
{
FILE *fpin;
char p[1024];
char *temppath;
char *temp = (char *)calloc(1024, sizeof(char));
path = (char *) getenv("PATH");
strcpy ( p, path );
path = strtok ( p, ":" ); // Find the first PATH
while ( path != NULL ) {
strcpy ( temp, path ); // Save a copy of substring
strcat ( temp, "/" ); // Form a path and file name
strcat ( temp, command );
if ( ( fpin = fopen ( temp, "r" ) ) == NULL ) {
temp[0] = '\0'; // Start over again
path = strtok ( ( char * ) 0, ":" ); // Try next path
} else {
break; // Must have a good fpin
}
}
if ( fpin == NULL ) {
return NULL;
} else {
return temp;
}
}
// this function was found on groups.google.com
// there was no author's name with the code...
void trim(char* name) {
char* p = name ;
size_t n ;
while (isspace(*p))
++p ;
if ((n = strlen(p)) > 0)
while (isspace(p[n-1]))
--n ;
((char*)memmove(name, p, n))[n] = '\0' ;
}
// the main program...
int main() {
CommandType *command = (CommandType*) malloc(sizeof(CommandType));
CommandType *command2 = (CommandType*) malloc(sizeof(CommandType));
int count;
int runmode;
int piped;
char* redirectionFilename;
char* buffer = (char*)calloc(1024, sizeof(char));
while(TRUE){
piped = FALSE;
redirectionType = DEFAULT;
input = (char *)calloc(1024, sizeof(char));
redirectionFilename = (char *)calloc(1024, sizeof(char));
// print the prompt
printf("%s(%s)> ", PROMPT, getcwd(buffer, 1024));
gets(input);
trim(input);
// start over if a blank line happens
if ((strcmp(input, "") != 0) && (strcmp(input, ".") != 0) && (strcmp(input, "..") != 0)) {
// checks of exit or quit, and terminates program if seen
if ((strcmp(input, "quit")== 0) || (strcmp(input, "exit")== 0)) {
printf("Terminating Shell...\n");
return 0;
}
// initialize argv array
command->argv = (char**)calloc(256, sizeof(char*));
command2->argv = (char**)calloc(256, sizeof(char*));
// parses the command line
ptr = strtok(input, " ");
command->name = ptr;
command->argv[0] = ptr;
command->argc = 1;
count = 1;
runmode = NORMALMODE;
ptr = strtok (NULL, " ");
while (ptr != NULL) {
//command->argv[count++] = ptr;
if (strcmp(ptr, "|")==0) {
// pipe found
if (piped) {
printf("Error: Second level piping not supported.\n");
} else {
// set up parser to read into the 2nd command
piped = TRUE;
ptr = strtok (NULL, " ");
if (ptr != NULL) {
command2->name = ptr;
command2->argv[0] = ptr;
command2->argc = 1;
count = 1;
} else {
printf("Error: No command to pipe.\n");
}
}
} else if (strcmp(ptr, ">")==0) {
ptr = strtok (NULL, " ");
if (ptr != NULL) {
redirectionFilename = ptr;
redirectionType = STDOUT;
ptr = NULL; // used to break while loop
} else {
printf("Error: No file specified for redirection.\n");
}
} else if (strcmp(ptr, "<")==0) {
ptr = strtok (NULL, " ");
if (ptr != NULL) {
redirectionFilename = ptr;
redirectionType = STDIN;
ptr = NULL; // used to break while loop
} else {
printf("Error: No file specified for redirection.\n");
}
} else {
if (piped) {
command2->argv[count++] = ptr;
command2->argc++;
} else {
command->argv[count++] = ptr;
command->argc++;
}
}
ptr = strtok (NULL, " ");
}
if (piped) {
runPipedCommands(command, command2);
} else if (redirectionType != DEFAULT) {
runRedirectedCommand(command, redirectionFilename, redirectionType);
} else {
if (strcmp(command->argv[command->argc-1],"&")==0) {
// & found, remove it from argv list
runmode = CONCURRENTMODE;
command->argv[command->argc-1] = NULL;
}
// check for built-in commands
if (strcmp(command->argv[0], "echo") == 0) {
// echo the commandline tokens
int i;
for (i = 1; i < command->argc; i++) {
printf("%s ", command->argv[i]);
}
printf("\n");
} else if (strcmp(command->argv[0],"cd") == 0) {
// change directory
if (command->argc == 2)
{ if (chdir(command->argv[1]) != 0)
printf("Error: Invalid directory.\n");
}
else if(command->argc==1)
{
if(chdir(getenv("HOME"))!=0)
printf("error:could not cd");
}
else
printf("Error: Invalid use of cd command.\n");
} else if (strcmp(command->argv[0],"getenv") == 0) {
if (command->argc == 2) {
char* variable = (char *) getenv(command->argv[1]);
if (variable == NULL) {
printf("Error: Invalid environment variable.\n");
} else {
printf("%s\n", variable);
}
} else {
printf("Error: Invalid use of getenv command.\n");
}
} else if (strcmp(command->argv[0],"setenv") == 0) {
if (command->argc == 3) {
char* value = (char*)calloc(1024,sizeof(char));
strcpy(value, command->argv[1]);
strcat(value, "=");
strcat(value, command->argv[2]);
putenv(value);
} else {
printf("Error: Invalid use of getenv command.\n");
}
} else {
// run the command as regular command....
if (runmode == NORMALMODE) {
runCommand(command);
} else if (runmode == CONCURRENTMODE) {
runConcurrentCommand(command);
}
}
} // if (piped)
}
}
}
// runs a command normally
int runCommand(CommandType* command) {
char* filename = getCommandPath(command->name);
if (filename == NULL) {
printf("Command not found.\n");
return 1;
}
// creates child process
pid = fork();
// checks for error
if (pid < 0) {
printf("Error in the fork process.\n");
return 1;
} else if (pid == 0) {
// Child code
execv(filename, command->argv);
return 1;
} else {
// Parent waits
while (wait(&status) != pid);
}
}
// runs a command as a background process
int runConcurrentCommand(CommandType* command) {
char* filename = getCommandPath(command->name);
if (filename == NULL) {
printf("Command not found.\n");
return 1;
}
// creates child process
pid = fork();
// checks for error
if (pid < 0) {
printf("Error in the fork process.\n");
return 1;
} else if (pid == 0) {
// Child code
execv(filename, command->argv);
return 1;
} else {
// Parent doesn't wait
//while (wait(&status) != pid);
}
}
// pipes one command into another
int runPipedCommands(CommandType* command, CommandType* command2) {
char* filename2 =getCommandPath(command2->name);
char* filename = getCommandPath(command->name);
int fd[2];
if (filename == NULL) {
printf("%s command not found.\n", command->name);
return 1;
}
if (filename2 == NULL) {
printf("%s command not found.\n", command2->name);
return 1;
}
if (pipe(fd) == -1) {
printf("Error: Pipe failed.\n");
return 1;
}
if ((pid = fork()) < 0) {
printf("Error: Fork failed.\n");
return 1;
}
if (pid == 0) {
// child process
close(fd[1]);
dup2(fd[0], 0);
close(fd[0]);
execv(filename2, command2->argv);
printf("Error: execv failed.\n");
return 1;
} else {
// parent process
// need to fork again, so the shell isn't replaced
int pid2;
int pid;
if ((pid2 = fork()) < 0) {
printf("Error: Fork failed.\n");
return 1;
}
if (pid2 == 0) {
// child process
close(fd[0]);
dup2(fd[1], 1);
close(fd[1]);
execv(filename, command->argv);
printf("Error: execv failed.\n");
return 1;
} else {
// parent process (the shell)
close(fd[0]);
close(fd[1]);
while (wait(&status) != pid2);
}
}
return 0;
}
// redirects STDIN or STDOUT for a command
int runRedirectedCommand(CommandType* command, char* file, int fileid) {
char* filename = getCommandPath(command->name);
if (filename == NULL) {
printf("%s command not found.\n", command->name);
return 1;
}
if ((pid = fork()) < 0) {
printf("Error: Fork failed.\n");
return 1;
}
if (pid == 0) {
// child process
int fid;
if (fileid == STDIN) {
fid = open(file, O_RDONLY, 0600);
} else if (fileid == STDOUT) {
fid = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
}
dup2(fid, fileid);
close(fid);
execv(filename, command->argv);
printf("Error: execv failed.\n");
return 1;
} else {
// parent process (shell)
while (wait(&status) != pid);
}
}