Skip to content

Commit

Permalink
Inital commit V1.0 Praktikum2
Browse files Browse the repository at this point in the history
  • Loading branch information
moritz31 committed Apr 24, 2017
1 parent c98dd86 commit ae4481c
Show file tree
Hide file tree
Showing 5 changed files with 435 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ $RECYCLE.BIN/
*.lnk

# Netbeans
nbproject/private/
nbproject/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
.dep.inc
128 changes: 128 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed directly, and they are:
#
# build build a specific configuration
# clean remove built files from a configuration
# clobber remove all built files
# all build all configurations
# help print help mesage
#
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
# .help-impl are implemented in nbproject/makefile-impl.mk.
#
# Available make variables:
#
# CND_BASEDIR base directory for relative paths
# CND_DISTDIR default top distribution directory (build artifacts)
# CND_BUILDDIR default top build directory (object files, ...)
# CONF name of current configuration
# CND_PLATFORM_${CONF} platform name (current configuration)
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
#
# NOCDDL


# Environment
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin


# build
build: .build-post

.build-pre:
# Add your pre 'build' code here...

.build-post: .build-impl
# Add your post 'build' code here...


# clean
clean: .clean-post

.clean-pre:
# Add your pre 'clean' code here...

.clean-post: .clean-impl
# Add your post 'clean' code here...


# clobber
clobber: .clobber-post

.clobber-pre:
# Add your pre 'clobber' code here...

.clobber-post: .clobber-impl
# Add your post 'clobber' code here...


# all
all: .all-post

.all-pre:
# Add your pre 'all' code here...

.all-post: .all-impl
# Add your post 'all' code here...


# build tests
build-tests: .build-tests-post

.build-tests-pre:
# Add your pre 'build-tests' code here...

.build-tests-post: .build-tests-impl
# Add your post 'build-tests' code here...


# run tests
test: .test-post

.test-pre: build-tests
# Add your pre 'test' code here...

.test-post: .test-impl
# Add your post 'test' code here...


# help
help: .help-post

.help-pre:
# Add your pre 'help' code here...

.help-post: .help-impl
# Add your post 'help' code here...



# include project implementation makefile
include nbproject/Makefile-impl.mk

# include project make variables
include nbproject/Makefile-variables.mk
153 changes: 153 additions & 0 deletions ShellInterpreter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* File: ShellInterpreter.cpp
* Author: debian
*
* Created on 24. April 2017, 10:51
*/

#include "ShellInterpreter.h"

#include <string.h>
#include <iterator>
#include <sstream>
#include <unistd.h>
#include <stdio.h>
#include <algorithm>
#include <sys/wait.h> // std::transform

ShellInterpreter::ShellInterpreter() {
this->isRunning = true;
this->shell_prompt = "$";
this->processWait = true;
}

ShellInterpreter::ShellInterpreter(const ShellInterpreter& orig) {
}

ShellInterpreter::~ShellInterpreter() {
}

/**
* @brief Mainloop of the shell
*/
void ShellInterpreter::update() {

// Loop until we should exit
while(this->isRunning) {

//Clean all input
this->cleanUp();

//Retrieve input
this->getUserInput();

//Validate input
if(this->formatInput()) {
//Execute input
this->executeProcess();
}
}
}

/**
* @brief Cleans all used var in this class for the next processing
*/
void ShellInterpreter::cleanUp(void) {

// Clear each char* with NULL to be safe
for(int i = 0; i < this->execBuffer.size();i++) {
this->execBuffer[i] = NULL;
}
this->execBuffer.clear(); // Clear the vector
this->buffer.clear(); // Clear the string
this->processWait = true; // Rest the wait to default
}

/**
* @brief Outputs the shell prompt and retrieve the user input
*/
void ShellInterpreter::getUserInput(void) {

std::cout << shell_prompt << " ";
getline(std::cin,this->buffer);

}

/**
* @brief Convert a string to an char*
* @param s string which should be converted
* @return returns an char* which contains the string
*/
static char *convert(const std::string & s)
{
char *pc = new char[s.size()+1];
strcpy(pc, s.c_str());
return pc;
}

/**
* @brief Converts the input which is formated as a string into an array of char* which can be passed to execvp
* @return returns if the input is valid or not
*/
bool ShellInterpreter::formatInput() {

// If the inputBuffer is empty we do not have to do anything
if(this->buffer.empty()) {
return false;
} else if(this->buffer == "logout") {
this->isRunning = false;
return false;
}

// Create a stringstream from a buffer and pass the string to the vector
std::stringstream ss(this->buffer);
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;

std::vector<std::string> vstrings(begin,end);

// Check for & sign to get process fork info
if(vstrings.at(vstrings.size()-1) == "&") {
vstrings.pop_back();
this->processWait = false;
}

// Transform string vector to char* vector
std::transform(vstrings.begin(),vstrings.end(),std::back_inserter(this->execBuffer),convert);

return true;
}

/**
* @brief Forks an process and wait for finish depending on wait flag set
*/
void ShellInterpreter::executeProcess(void) {

int pid;

// Try to fork a child process
if((pid = fork()) < 0) {

std::cout << "[ERROR] Forking process" << std::endl;
//Error while forking
exit(1);
} else if(pid == 0) { // If we are the child process try to run the command

// Try to execute the buffer
if(execvp(this->execBuffer[0],this->execBuffer.data()) < 0) {

std::cout << "[ERROR] Executing process" << std::endl;
// Error while running
exit(1);
}

}

// If we want to wait for an process to finish we need to call waitpid
if(this->processWait) {
waitpid(pid,NULL,0);
} else {
std::cout << "[PID] " << pid << std::endl;
}

}
40 changes: 40 additions & 0 deletions ShellInterpreter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* File: ShellInterpreter.h
* Author: debian
*
* Created on 24. April 2017, 10:51
*/

#ifndef SHELLINTERPRETER_H
#define SHELLINTERPRETER_H

#include <iostream>
#include <string.h>
#include <vector>

class ShellInterpreter {
public:
ShellInterpreter();
ShellInterpreter(const ShellInterpreter& orig);

void update();

virtual ~ShellInterpreter();
private:

std::string buffer;
std::vector<char*> execBuffer;
bool isRunning;
std::string shell_prompt;
bool processWait;

void cleanUp(void);
void getUserInput(void);
bool formatInput(void);
void executeProcess(void);


};

#endif /* SHELLINTERPRETER_H */

Loading

0 comments on commit ae4481c

Please sign in to comment.