Initial commit pushing project source
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#ignore a test version of the cat.java file
|
||||
cat2.java
|
||||
596
GdBShell.java
Normal file
596
GdBShell.java
Normal file
@@ -0,0 +1,596 @@
|
||||
import static cTools.KernelWrapper.*; //imports a Java Wrapper for C kernel functions, needs the sourced source_me
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
import java.lang.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
//TODO: switch case for printcolor
|
||||
|
||||
|
||||
//TODO: implement auto source?
|
||||
|
||||
public class main{
|
||||
|
||||
public static void main(String[] args){
|
||||
|
||||
|
||||
System.out.println("Welcome!");
|
||||
String shellPrefix = "EN@GdBShell:";//print actual user instead of EN??
|
||||
int runningInt = 0;
|
||||
Scanner scn = new Scanner(System.in);
|
||||
while (true){
|
||||
|
||||
parseInput(getInput(runningInt,shellPrefix, scn));
|
||||
runningInt++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static String[] getInput(int runningInt, String shellPrefix, Scanner scn){
|
||||
|
||||
|
||||
String directoryPath = System.getProperty("user.dir");
|
||||
String[] directoryArray = directoryPath.split("/");
|
||||
StringBuffer buffer = new StringBuffer("~");
|
||||
|
||||
|
||||
//gets rid of the home/user directory and builds a string
|
||||
for (int i=3;(i<directoryArray.length);i++){
|
||||
buffer.append("/");
|
||||
buffer.append(directoryArray[i]);
|
||||
}
|
||||
System.out.print("("+runningInt+")");
|
||||
printColor(shellPrefix,"purple",false);
|
||||
printColor(buffer.toString()+"$ ","cyan",false);
|
||||
|
||||
String input= scn.nextLine();//get input
|
||||
|
||||
String[] inputArray = input.split(" ");
|
||||
|
||||
//get rid of spaces and tabs
|
||||
int countInputs = 0;
|
||||
int[] countArray = new int[inputArray.length];
|
||||
//count all inputs that actually contain something and put them in a new array in the second for loop
|
||||
for (int i =0;i< inputArray.length;i++){
|
||||
if (inputArray[i].equals(" ")||inputArray[i].equals(" ")||inputArray[i].equals("")){
|
||||
;
|
||||
}
|
||||
else{
|
||||
countArray[countInputs]=i;
|
||||
countInputs++;
|
||||
}
|
||||
}
|
||||
//System.out.println(Arrays.toString(countArray));
|
||||
String[] returnArray = new String[countInputs];
|
||||
for (int i=0; i<countInputs;i++){
|
||||
returnArray[i]= inputArray[(countArray[i])];
|
||||
}
|
||||
|
||||
return returnArray;
|
||||
//return replaceCat(returnArray);
|
||||
}
|
||||
|
||||
static void parseInput(String[] inputArray){
|
||||
|
||||
//System.out.println(inputArray.length + Arrays.toString(inputArray));
|
||||
//check for empty inputs
|
||||
if (inputArray.length<=1){
|
||||
if(inputArray.length==0){return;}
|
||||
if(inputArray[0].equals(" ")){return;}
|
||||
if(inputArray[0].equals(" ")){return;}
|
||||
|
||||
}
|
||||
|
||||
//implements the exit terminal function
|
||||
if (inputArray[0].equals("exit")){
|
||||
if (inputArray.length==1){
|
||||
printColor("Session ended by user","red",true);
|
||||
System.exit(0);
|
||||
}
|
||||
else{
|
||||
printColor( "\"exit\" doesn't take parameters. It will end this current shell. Did you try to find a different executable?","red",true);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//find concats with && in input and execute only if previous command was successful
|
||||
ArrayList<Integer> concatPosition = new ArrayList<Integer>();
|
||||
//save the positions of concats
|
||||
for (int i=0; i<inputArray.length;i++){
|
||||
if(inputArray[i].equals("&&")){
|
||||
concatPosition.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//for testing***************, prints the positions of the concats
|
||||
for (int i=0;i<concatPosition.size();i++){
|
||||
printColor(Integer.toString(concatPosition.get(i))+" ","yellow",false);
|
||||
}
|
||||
|
||||
//**************************
|
||||
*/
|
||||
|
||||
//if there are any concats
|
||||
if(concatPosition.size()>0){
|
||||
|
||||
//split the inputArray into singular commands that were separated by &&
|
||||
|
||||
ArrayList<ArrayList<String>> commandsList = new ArrayList<ArrayList<String>>();
|
||||
for (int i=0;i<concatPosition.size()+1;i++){
|
||||
commandsList.add( new ArrayList<String>());
|
||||
}
|
||||
//upper Arraylist used with fixed size, doesnt throw warning like using an array would
|
||||
//because one concat splits the input into two parts --->+1
|
||||
|
||||
//iterate over every command except last, because no concat comes after the last one
|
||||
int prevConcatPos=0;
|
||||
for (int i=0;i<concatPosition.size();i++){
|
||||
|
||||
for(int j=prevConcatPos;j<concatPosition.get(i);j++){
|
||||
(commandsList.get(i)).add(inputArray[j]);
|
||||
}
|
||||
prevConcatPos=concatPosition.get(i)+1;
|
||||
}
|
||||
//add last command
|
||||
for (int i=concatPosition.get(concatPosition.size()-1)+1;i<inputArray.length;i++){
|
||||
(commandsList.get(commandsList.size()-1)).add(inputArray[i]);
|
||||
}
|
||||
|
||||
//execute commands in commandsList if previous command was successful, ie terminated with code 0
|
||||
int returnValue = 0;
|
||||
for(int i=0;i<commandsList.size();i++){
|
||||
//if previous command successful
|
||||
if (returnValue==0){
|
||||
|
||||
//build array from arraylist that contains command
|
||||
String[] command = new String[commandsList.get(i).size()];
|
||||
for (int j=0;j<command.length;j++){
|
||||
command[j]= commandsList.get(i).get(j);
|
||||
}
|
||||
|
||||
//execute command and save return value
|
||||
returnValue = parseRedirect(command);
|
||||
}
|
||||
|
||||
//if it wasnt successful
|
||||
else{
|
||||
//build command as string that wasnt succcessful
|
||||
int failedCommandNumber = i-1;
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
for (int j=0;j<commandsList.get(failedCommandNumber).size();j++){
|
||||
buffer.append(commandsList.get(failedCommandNumber).get(j));
|
||||
}
|
||||
|
||||
|
||||
printColor("Stopped concatenation at command number "+ failedCommandNumber +" \""+buffer.toString()+"\"","red",true);
|
||||
|
||||
if(returnValue==Integer.MIN_VALUE){
|
||||
printColor("Couldn't find executable assigned to \""+ commandsList.get(failedCommandNumber).get(0)+"\"","red",true);
|
||||
}
|
||||
else{
|
||||
printColor("Exited with error code "+returnValue,"red",true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if its only one command without concats
|
||||
else{
|
||||
int returnValue = parseRedirect(inputArray);
|
||||
if (returnValue==0){
|
||||
printColor("Process exited without error","green",true);
|
||||
}
|
||||
else{
|
||||
if(returnValue == Integer.MIN_VALUE){
|
||||
printColor("Couldn't find executable assigned to \""+ inputArray[0]+"\"","red",true);
|
||||
}
|
||||
else{
|
||||
printColor("Process exited with code "+ returnValue,"red",true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;//TODO: clean up error messages
|
||||
}
|
||||
|
||||
static int parseRedirect(String[] inputArray){//should take pipe and read/write,, add >> for append?
|
||||
//find last occurrences of < and >
|
||||
int redirectInPos = -1;
|
||||
int redirectOutPos = -1;
|
||||
boolean setFirstBool = true;
|
||||
int firstPos = inputArray.length;
|
||||
for(int i=0;i< inputArray.length;i++){
|
||||
if(inputArray[i].equals("<")){
|
||||
redirectInPos = i;
|
||||
if(setFirstBool){
|
||||
firstPos=i;
|
||||
setFirstBool = false;
|
||||
}
|
||||
}
|
||||
if(inputArray[i].equals(">")){
|
||||
redirectOutPos = i;
|
||||
if(setFirstBool){
|
||||
firstPos=i;
|
||||
setFirstBool = false;
|
||||
}
|
||||
}
|
||||
/*if(inputArray[i].equals(">>")){
|
||||
appendOutPos = i;
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
int fd_in=-1;
|
||||
if(redirectInPos!=-1){
|
||||
if(checkls(inputArray[redirectInPos+1])){
|
||||
fd_in = open(inputArray[redirectInPos+1],O_RDONLY);
|
||||
}
|
||||
else{return -10;}//throw error because invalid input file
|
||||
}
|
||||
|
||||
int fd_out=-1;
|
||||
if(redirectOutPos!=-1){
|
||||
fd_out = open(inputArray[redirectOutPos+1],O_WRONLY|O_CREAT|O_TRUNC);//create file if non existent, overwrite if it is
|
||||
}
|
||||
|
||||
String[] commands = new String[firstPos];
|
||||
for (int i=0;i< commands.length;i++){
|
||||
commands[i]=inputArray[i];
|
||||
}
|
||||
int returnValue= parsePipe(commands,fd_in,fd_out);
|
||||
if(fd_in!=-1){
|
||||
close(fd_in);
|
||||
}
|
||||
if(fd_out!= -1){
|
||||
close(fd_out);
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
|
||||
static int parsePipe(String[] inputArray,int fd_in, int fd_out){
|
||||
int returnValue = -5;
|
||||
ArrayList<Integer> pipePos = new ArrayList<Integer>();
|
||||
int count =0;
|
||||
for (int i =0;i< inputArray.length; i++){
|
||||
if (inputArray[i].equals("|")){
|
||||
pipePos.add(count);
|
||||
count=0;
|
||||
|
||||
}
|
||||
else{count++;}
|
||||
}
|
||||
pipePos.add(count);
|
||||
|
||||
//populate array of commands separated by |
|
||||
String[][] commands = new String[pipePos.size()][];
|
||||
int prevPipePos = 0;
|
||||
for (int i=0;i< pipePos.size();i++){
|
||||
commands[i] = new String[pipePos.get(i)];
|
||||
for (int j=0;j<commands[i].length;j++){
|
||||
commands[i][j]=inputArray[j+prevPipePos];
|
||||
}
|
||||
prevPipePos = prevPipePos + pipePos.get(i)+1;
|
||||
}
|
||||
|
||||
//execute commands
|
||||
//first command gets stdin
|
||||
int lastIn = -1;
|
||||
int[] pipefd = new int[2];
|
||||
if(commands.length>1){
|
||||
pipe(pipefd);
|
||||
returnValue= execute(commands[0],fd_in,pipefd[1]);
|
||||
for(int i=1;i<commands.length-1;i++){
|
||||
returnValue = execute(commands[i],pipefd[0],pipefd[1]);
|
||||
|
||||
}
|
||||
lastIn = pipefd[0];
|
||||
System.err.println("here");
|
||||
}
|
||||
else{
|
||||
lastIn = fd_in;
|
||||
}
|
||||
// execute last (or only) command
|
||||
returnValue = execute(commands[commands.length-1],lastIn,fd_out);
|
||||
|
||||
|
||||
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int execute(String[] inputArray,int fd_in, int fd_out){//0 for read, 1 for write
|
||||
int[] intArray = new int[]{Integer.MIN_VALUE};//to pass to the waitpid function
|
||||
//split the Array into path and arguments
|
||||
|
||||
//tries to find the executable at first position of input
|
||||
String path = null;
|
||||
if (inputArray.length!=0){
|
||||
|
||||
String input = inputArray[0];
|
||||
/*
|
||||
if (input.indexOf("/")>-1){
|
||||
if (checkls(input)==true){
|
||||
|
||||
path = input;
|
||||
}
|
||||
}
|
||||
else{*/
|
||||
path = which(input);
|
||||
//}
|
||||
}
|
||||
else{return Integer.MIN_VALUE+1;}// add error in parseInput for this number
|
||||
|
||||
|
||||
|
||||
|
||||
//if path found, compile argslist and start execv
|
||||
if (isNumeric(path)==false){
|
||||
printColor("Executing program at "+path,"green",true);
|
||||
//System.out.println();
|
||||
|
||||
//int[] pipeArray = new int[]{0};//sets the pip
|
||||
int forkInt = fork();// saves the return value because every call will fork the process again
|
||||
|
||||
|
||||
|
||||
|
||||
//baby process
|
||||
if (forkInt==0){
|
||||
//Array[0] mit rest als parameter ausführen (path, args[])
|
||||
|
||||
//read from pipe or write to it
|
||||
if(fd_in!=-1){
|
||||
close(0);
|
||||
dup2(fd_in,0);
|
||||
}
|
||||
if(fd_out!=-1){
|
||||
close(1);
|
||||
dup2(fd_out,1);
|
||||
}
|
||||
|
||||
//execute the program
|
||||
execv(path, inputArray);
|
||||
printColor("execv fatal error","red",true);
|
||||
exit(0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//papa process
|
||||
else{
|
||||
|
||||
waitpid(forkInt,intArray,0);
|
||||
|
||||
//read from pipe HEEERE???
|
||||
}
|
||||
}
|
||||
return intArray[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String which(String arguments){
|
||||
ProcessBuilder prcBuilder = new ProcessBuilder();
|
||||
prcBuilder.command("bash","-c","which "+arguments);
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
Process process = prcBuilder.start();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
|
||||
String line =null;
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
while ((line=reader.readLine())!=null){
|
||||
buffer.append(line);
|
||||
}
|
||||
String path = buffer.toString();
|
||||
if (path.contains("/")){
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
else{
|
||||
int exitCode = process.waitFor();
|
||||
return Integer.toString(exitCode);
|
||||
//System.out.println("\nExited with error code : " + exitCode);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
printColor("err1","red",true); //e.toString();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
printColor("err2","red",true); //e.toString();
|
||||
}
|
||||
|
||||
return "t";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static boolean checkls(String input){
|
||||
|
||||
//check what ls does in this program if executed locally
|
||||
String[] inputArray = input.split("/");
|
||||
String checkfile = inputArray[inputArray.length-1];
|
||||
StringBuffer buffer1 = new StringBuffer();
|
||||
if (input.indexOf("/")==0){
|
||||
buffer1.append("/");
|
||||
}
|
||||
for (int i=0;i<inputArray.length;i++){
|
||||
buffer1.append(inputArray[i]);
|
||||
if(i<inputArray.length-1){
|
||||
buffer1.append("/");
|
||||
}
|
||||
}
|
||||
//System.out.println(buffer1);
|
||||
|
||||
ProcessBuilder prcBuilder = new ProcessBuilder();
|
||||
prcBuilder.command("bash","-c","ls "+buffer1.toString());
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
Process process = prcBuilder.start();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
|
||||
String line =null;
|
||||
StringBuffer buffer2 = new StringBuffer();
|
||||
while ((line=reader.readLine())!=null){
|
||||
buffer2.append(line);
|
||||
buffer2.append(" ");
|
||||
}
|
||||
String path = buffer2.toString();
|
||||
//printColor(path,"yellow",true);//for test purposes
|
||||
if (path.contains(checkfile)){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else{
|
||||
int exitCode = process.waitFor();
|
||||
return false;
|
||||
//System.out.println("\nExited with error code : " + exitCode);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
printColor("err1","red",true); //e.toString();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
printColor("err2","red",true); //e.toString();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNumeric(String toCheck){
|
||||
try{
|
||||
double d = Double.parseDouble(toCheck);
|
||||
}
|
||||
catch(NumberFormatException nsfw){
|
||||
return false;
|
||||
}
|
||||
catch(NullPointerException npe){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static boolean printColor(String text, String colorvar, boolean lineBreak){// maybe rainbow??
|
||||
//takes two Strings and one boolean that specify the text to print, the color and if there should be a linebreak (ie print or println)
|
||||
|
||||
String ANSI_RESET = "\u001B[0m";
|
||||
String ANSI_BLACK = "\u001B[30m";
|
||||
String ANSI_RED = "\u001B[31m";
|
||||
String ANSI_YELLOW = "\u001B[33m";
|
||||
String ANSI_BLUE = "\u001B[34m";
|
||||
String ANSI_PURPLE = "\u001B[35m";
|
||||
String ANSI_CYAN = "\u001B[36m";
|
||||
String ANSI_WHITE = "\u001B[37m";
|
||||
String ANSI_GREEN = "\u001B[32m";
|
||||
|
||||
boolean returnBool= true;
|
||||
String color= colorvar.toLowerCase();
|
||||
|
||||
if (color.equals("white")){
|
||||
color=ANSI_WHITE;
|
||||
}
|
||||
else{
|
||||
if (color.equals("black")){
|
||||
color=ANSI_BLACK;
|
||||
}
|
||||
else{
|
||||
if (color.equals("yellow")){
|
||||
color=ANSI_YELLOW;
|
||||
}
|
||||
else{
|
||||
if (color.equals("blue")){
|
||||
color=ANSI_BLUE;
|
||||
}
|
||||
else{
|
||||
if (color.equals("purple")){
|
||||
color=ANSI_PURPLE;
|
||||
}
|
||||
else{
|
||||
if (color.equals("cyan")){
|
||||
color=ANSI_CYAN;
|
||||
}
|
||||
else{
|
||||
if (color.equals("red")){
|
||||
color=ANSI_RED;
|
||||
}
|
||||
else{
|
||||
if (color.equals("green")){
|
||||
color=ANSI_GREEN;
|
||||
}
|
||||
else{
|
||||
System.out.print(text);
|
||||
returnBool = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.print(color+text + ANSI_RESET);
|
||||
|
||||
if (lineBreak){
|
||||
System.out.println("");
|
||||
}
|
||||
return returnBool;
|
||||
}
|
||||
|
||||
static String[] replaceCat(String[] args){//used to integrate custom cat into shell
|
||||
if (args[0].equals("jcat")){
|
||||
String[] changed = new String[args.length+1];
|
||||
changed[0]= "java";
|
||||
changed[1]= "cat.java";
|
||||
|
||||
for (int i=1;i<args.length;i++){//ignore the "jcat" at first pos
|
||||
changed[i+1]=args[i];
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
else{return args;}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
138
cTools/KernelWrapper.c
Normal file
138
cTools/KernelWrapper.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <jni.h>
|
||||
#include "KernelWrapper.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // calloc
|
||||
#include <unistd.h> // _exit, fork, lseek, read, write, close, dup2
|
||||
#include <fcntl.h> // open
|
||||
#include <sys/types.h> // waitpid, opendir, closedir, open, lseek
|
||||
#include <sys/wait.h> // waitpid
|
||||
#include <sys/stat.h> // open
|
||||
#include <dirent.h> // opendir, readdir, closedir
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_exit(JNIEnv *env, jclass clazz, jint rc) {
|
||||
_exit(rc);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_fork(JNIEnv *env, jclass clazz) {
|
||||
pid_t pid;
|
||||
if ( (pid = fork()) == -1) { perror("KernelWrapper fork"); }
|
||||
return pid;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_waitpid(JNIEnv *env, jclass clazz, jint pid, jintArray status, jint options) {
|
||||
int *stat = (*env)->GetIntArrayElements(env, status, 0);
|
||||
pid_t p = waitpid(pid, stat, options);
|
||||
if (p==-1) perror("KernelWrapper waitpid");
|
||||
(*env)->ReleaseIntArrayElements(env, status, stat, 0);
|
||||
return p;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_execv( JNIEnv *env, jclass clazz, jstring path, jobjectArray argv ) {
|
||||
const char *c_path = (*env)->GetStringUTFChars(env, path, 0);
|
||||
char **c_argv = calloc(sizeof(char*), (*env)->GetArrayLength(env, argv)+2);
|
||||
for (int i = 0; i < (*env)->GetArrayLength(env, argv); i++)
|
||||
c_argv[i] = (char*)(*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, argv, i), 0);
|
||||
if (execv(c_path, (char *const*)c_argv) == -1) { perror("KernelWrapper execv"); return -1; }
|
||||
fprintf(stderr, "\nHow did you get here?!?\n"); exit(1);
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_cTools_KernelWrapper_readdir(JNIEnv *env, jclass clazz, jstring path) {
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
const char *c_path = (*env)->GetStringUTFChars(env, path, 0);
|
||||
|
||||
if ( ! (dp = opendir(c_path)) ) { perror("KernelWrapper opendir"); return 0; }
|
||||
|
||||
int size = -1;
|
||||
do {
|
||||
size++;
|
||||
errno = 0;
|
||||
ep = readdir(dp);
|
||||
if (errno) { perror("KernelWrapper readdir"); return 0; }
|
||||
} while (ep);
|
||||
|
||||
rewinddir(dp);
|
||||
jobjectArray array = (*env)->NewObjectArray(env, size, (*env)->FindClass(env, "java/lang/String"), 0);
|
||||
for (int i = 0; ep = readdir(dp); i++)
|
||||
(*env)->SetObjectArrayElement(env, array, i, (*env)->NewStringUTF(env, ep->d_name));
|
||||
closedir(dp);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, path, c_path);
|
||||
return array;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_cTools_KernelWrapper_get_1current_1dir_1name(JNIEnv *env, jclass clazz) {
|
||||
char *xxx=get_current_dir_name();
|
||||
return (*env)->NewStringUTF(env, xxx);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_open( JNIEnv *env, jclass clazz, jstring path, jint flags ) {
|
||||
const char *c_path = (*env)->GetStringUTFChars(env, path, 0);
|
||||
int file;
|
||||
if ( (file = open(c_path, flags, 0666)) == -1) { perror("KernelWrapper open"); }
|
||||
(*env)->ReleaseStringUTFChars(env, path, c_path);
|
||||
return file;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_close( JNIEnv *env, jclass clazz, jint fd ) {
|
||||
int err;
|
||||
if ( (err = close(fd)) == -1) { perror("KernelWrapper close"); }
|
||||
return err;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_lseek( JNIEnv *env, jclass clazz, jint fd, jint offset, jint whence ) {
|
||||
int bytes;
|
||||
if ( (bytes = lseek(fd, offset, whence)) == -1) { perror("KernelWrapper lseek"); exit(1); }
|
||||
return bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_read( JNIEnv *env, jclass clazz, jint fd, jbyteArray buf, jint count ) {
|
||||
unsigned char *c_buf = (*env)->GetByteArrayElements(env, buf, 0);
|
||||
int bytes;
|
||||
if ( (bytes = read(fd, c_buf, count)) == -1) { perror("KernelWrapper read"); exit(1); }
|
||||
(*env)->ReleaseByteArrayElements(env, buf, c_buf, 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_readOffset( JNIEnv *env, jclass clazz, jint fd, jbyteArray buf, jint offset, jint count ) {
|
||||
unsigned char *c_buf = (*env)->GetByteArrayElements(env, buf, 0);
|
||||
int bytes;
|
||||
if ( (bytes = read(fd, c_buf+offset, count)) == -1) { perror("KernelWrapper read"); }
|
||||
(*env)->ReleaseByteArrayElements(env, buf, c_buf, 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_write( JNIEnv *env, jclass clazz, jint fd, jbyteArray buf, jint count ) {
|
||||
unsigned char *c_buf = (*env)->GetByteArrayElements(env, buf, 0);
|
||||
int bytes;
|
||||
if ( (bytes = write(fd, c_buf, count)) == -1) { perror("KernelWrapper write"); }
|
||||
if (bytes != count) { fprintf(stderr, "Could not write everything!\nThis should not happen!\n"); }
|
||||
(*env)->ReleaseByteArrayElements(env, buf, c_buf, 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_writeOffset( JNIEnv *env, jclass clazz, jint fd, jbyteArray buf, jint offset, jint count ) {
|
||||
unsigned char *c_buf = (*env)->GetByteArrayElements(env, buf, 0);
|
||||
int bytes;
|
||||
if ( (bytes = write(fd, c_buf+offset, count)) == -1) { perror("KernelWrapper write"); }
|
||||
if (bytes != count) { fprintf(stderr, "Could not write everything!\nThis should not happen!\n"); }
|
||||
(*env)->ReleaseByteArrayElements(env, buf, c_buf, 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_dup2( JNIEnv *env, jclass clazz, jint oldfd, jint newfd ) {
|
||||
int fd;
|
||||
if ( (fd = dup2(oldfd, newfd)) == -1) perror("KernelWrapper dup2");
|
||||
return fd;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_pipe( JNIEnv *env, jclass clazz, jintArray pipefd ) {
|
||||
int *ary = (*env)->GetIntArrayElements(env, pipefd, 0);
|
||||
int rc = pipe(ary);
|
||||
if (rc==-1) { perror("KernelWrapper pipe"); }
|
||||
(*env)->ReleaseIntArrayElements(env, pipefd, ary, 0);
|
||||
return rc;
|
||||
}
|
||||
BIN
cTools/KernelWrapper.class
Normal file
BIN
cTools/KernelWrapper.class
Normal file
Binary file not shown.
133
cTools/KernelWrapper.h
Normal file
133
cTools/KernelWrapper.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class cTools_KernelWrapper */
|
||||
|
||||
#ifndef _Included_cTools_KernelWrapper
|
||||
#define _Included_cTools_KernelWrapper
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: exit
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_exit
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: fork
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_fork
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: waitpid
|
||||
* Signature: (I[II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_waitpid
|
||||
(JNIEnv *, jclass, jint, jintArray, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: execv
|
||||
* Signature: (Ljava/lang/String;[Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_execv
|
||||
(JNIEnv *, jclass, jstring, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: get_current_dir_name
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_cTools_KernelWrapper_get_1current_1dir_1name
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: open
|
||||
* Signature: (Ljava/lang/String;I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_open
|
||||
(JNIEnv *, jclass, jstring, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: close
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_close
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: lseek
|
||||
* Signature: (III)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_lseek
|
||||
(JNIEnv *, jclass, jint, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: read
|
||||
* Signature: (I[BI)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_read
|
||||
(JNIEnv *, jclass, jint, jbyteArray, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: readOffset
|
||||
* Signature: (I[BII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_readOffset
|
||||
(JNIEnv *, jclass, jint, jbyteArray, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: write
|
||||
* Signature: (I[BI)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_write
|
||||
(JNIEnv *, jclass, jint, jbyteArray, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: writeOffset
|
||||
* Signature: (I[BII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_writeOffset
|
||||
(JNIEnv *, jclass, jint, jbyteArray, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: pipe
|
||||
* Signature: ([I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_pipe
|
||||
(JNIEnv *, jclass, jintArray);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: readdir
|
||||
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_cTools_KernelWrapper_readdir
|
||||
(JNIEnv *, jclass, jstring);
|
||||
|
||||
/*
|
||||
* Class: cTools_KernelWrapper
|
||||
* Method: dup2
|
||||
* Signature: (II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_cTools_KernelWrapper_dup2
|
||||
(JNIEnv *, jclass, jint, jint);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
38
cTools/KernelWrapper.java
Normal file
38
cTools/KernelWrapper.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package cTools;
|
||||
|
||||
public class KernelWrapper {
|
||||
static {
|
||||
//System.out.println(System.getProperty("java.library.path"));
|
||||
System.loadLibrary("KernelWrapper"); // actually: libKernelWrapper.so
|
||||
}
|
||||
|
||||
public static int O_RDONLY = 0;
|
||||
public static int O_WRONLY = 1;
|
||||
public static int O_RDWR = 2;
|
||||
public static int O_CREAT = 64;
|
||||
public static int O_TRUNC = 512;
|
||||
public static int SEEK_SET = 0;
|
||||
public static int SEEK_CUR = 1;
|
||||
public static int SEEK_END = 2;
|
||||
public static int STDIN_FILENO = 0;
|
||||
public static int STDOUT_FILENO = 1;
|
||||
public static int STDERR_FILENO = 2;
|
||||
|
||||
public static native int exit(int rc);
|
||||
public static native int fork();
|
||||
public static native int waitpid(int pid, int[] status, int options);
|
||||
public static native int execv(String path, String[] argv);
|
||||
//public static native String get_current_dir_name();
|
||||
|
||||
public static native int open(String path, int flags);
|
||||
public static native int close(int fd);
|
||||
public static native int lseek(int fd, int offset, int whence);
|
||||
public static native int read(int fd, byte[] buf, int count);
|
||||
public static native int readOffset(int fd, byte[] buf, int offset, int count);
|
||||
public static native int write(int fd, byte[] buf, int count);
|
||||
public static native int writeOffset(int fd, byte[] buf, int offset, int count);
|
||||
|
||||
public static native int pipe(int[] pipefd);
|
||||
public static native String[] readdir(String path);
|
||||
public static native int dup2(int oldfd, int newfd);
|
||||
}
|
||||
8
cTools/Makefile
Normal file
8
cTools/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
KernelWrapper:
|
||||
javac KernelWrapper.java
|
||||
(cd ..; javah -o cTools/KernelWrapper.h cTools.KernelWrapper)
|
||||
gcc -std=c99 -shared -fpic -I /opt/jdk/include -I /opt/jdk/include/linux -o libKernelWrapper.so KernelWrapper.c
|
||||
#gcc -std=c99 -shared -fpic -I /usr/lib/jvm/java-7-openjdk-amd64/include -I /usr/lib/jvm/java-7-openjdk-amd64/include/linux -o libKernelWrapper.so KernelWrapper.c
|
||||
|
||||
clean:
|
||||
/bin/rm -f *.class KernelWrapper.h libKernelWrapper.so
|
||||
BIN
cTools/libKernelWrapper.so
Normal file
BIN
cTools/libKernelWrapper.so
Normal file
Binary file not shown.
202
cat.java
Normal file
202
cat.java
Normal file
@@ -0,0 +1,202 @@
|
||||
//the cat version that doesnt use lseek(), only read()
|
||||
|
||||
|
||||
import static cTools.KernelWrapper.*; //imports a Java Wrapper for C kernel functions, needs the sourced source_me
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Scanner;
|
||||
import java.util.Arrays;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
//implement
|
||||
public class cat{
|
||||
|
||||
public static void main(String[] args) {
|
||||
//double start = System.nanoTime();
|
||||
boolean[] errarr = {false};
|
||||
int count =0;
|
||||
boolean [] params = parseArgs(args);//extract parameters and remove them from args
|
||||
//System.out.println(Arrays.toString(args));//for testing
|
||||
boolean argsnull=true;
|
||||
for(int i=0;i<args.length;i++){
|
||||
if(args[i]!=null){
|
||||
argsnull=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (args.length==0||argsnull){//get input if without params
|
||||
inputLoop(params,count);
|
||||
}
|
||||
else{
|
||||
|
||||
//System.out.println(Arrays.toString(args));//for testing
|
||||
if (params[0]){
|
||||
//System.out.println("If you always seek help from others, you will never be able to achieve greatness on your own.");// r/im14andthisisdeep
|
||||
printFile("cat.txt",params,errarr,count);
|
||||
|
||||
}
|
||||
else{
|
||||
for (int i=0; i<args.length;i++){
|
||||
|
||||
if (args[i]!=null){
|
||||
if (args[i].equals("-")){//get input if file name is "-"
|
||||
count = inputLoop(params,count);
|
||||
}
|
||||
else{
|
||||
count = printFile(args[i],params,errarr,count); //output file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
double end = System.nanoTime()-start;
|
||||
end=end/(1000*1000*1000);
|
||||
System.out.println(end);
|
||||
*/
|
||||
//System.out.println();
|
||||
if(errarr[0]){System.exit(1);}
|
||||
else{System.exit(0);}
|
||||
}
|
||||
|
||||
static boolean[] parseArgs(String[] args){
|
||||
|
||||
boolean[] params = new boolean[3];
|
||||
for (int i =0;i<args.length;i++){
|
||||
|
||||
if(args[i].equals("--help")||args[i].equals("-s")||args[i].equals("-n")){
|
||||
|
||||
if (args[i].equals("--help")){params[0]=true;} //display help
|
||||
if (args[i].equals("-s")){params[1]=true;} //suppress empty lines
|
||||
if (args[i].equals("-n")){params[2]=true;} //enumerate lines
|
||||
|
||||
args[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
static int inputLoop(boolean[] params, int count){
|
||||
Scanner scn = new Scanner(System.in);
|
||||
int countEmpty=0;
|
||||
boolean printThisLine = true;
|
||||
while (true){
|
||||
|
||||
try{
|
||||
String buf = scn.nextLine();
|
||||
|
||||
if(params[1]&&buf.length()==0){
|
||||
countEmpty++;
|
||||
if(countEmpty>1){
|
||||
printThisLine = false;
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
countEmpty=0;
|
||||
printThisLine= true;
|
||||
}
|
||||
|
||||
if(printThisLine){
|
||||
|
||||
if(params[2]){
|
||||
System.out.print("\u001B[33m"+"["+Integer.toString(count)+"]"+"\u001B[0m");
|
||||
count++;
|
||||
}
|
||||
|
||||
System.out.println(buf);
|
||||
}
|
||||
}
|
||||
catch(NoSuchElementException e){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static int printFile(String f, boolean[] params, boolean[] errarr, int count){
|
||||
|
||||
|
||||
//System.out.println(Arrays.toString(params));
|
||||
int fd = open(f,O_RDONLY);
|
||||
int bufsz = Integer.MAX_VALUE/8; //test values?
|
||||
if (fd!=-1){
|
||||
byte[] bytes = new byte[bufsz];//add length
|
||||
int rd = read(fd,bytes,bufsz);
|
||||
close(fd);
|
||||
|
||||
byte[] cleanbytes = new byte[rd];
|
||||
|
||||
for (int i=0;i<rd;i++){
|
||||
cleanbytes[i]= bytes[i];
|
||||
}
|
||||
|
||||
|
||||
String s = new String(cleanbytes, StandardCharsets.UTF_8);
|
||||
String t = "";//length 0
|
||||
String u = "";
|
||||
|
||||
|
||||
|
||||
if(params[1]){//suppress multiple empty lines
|
||||
|
||||
for (int i=0;i<s.length();i++){
|
||||
|
||||
if(params[1]==true&&s.charAt(i)=='\n'&&(t.length()>2&&t.charAt(t.length()-1)=='\n'&&t.charAt(t.length()-2)=='\n')){;}
|
||||
else{t = t+s.charAt(i);}
|
||||
}
|
||||
}
|
||||
else{t=s;}
|
||||
|
||||
|
||||
if(params[2]){//enumerate lines
|
||||
u = u + "\u001B[33m"+"["+Integer.toString(count)+"]"+"\u001B[0m";
|
||||
count++;
|
||||
|
||||
for (int i=0;i<t.length();i++){
|
||||
u = u + t.charAt(i);
|
||||
if((t.charAt(i)=='\n')&&(i<(t.length()-1))){//if we just appended a line break and we arent at the end of the file
|
||||
u = u+"\u001B[33m"+"["+Integer.toString(count)+"]"+"\u001B[0m";
|
||||
//t=t+Integer.toString(count)+" ";
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else{u=t;}
|
||||
|
||||
//possibly append newline at end of file?
|
||||
/*
|
||||
if(u.charAt(u.length()-1)!='\n'){
|
||||
u = u+ '\n';
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
System.out.print(u);
|
||||
|
||||
|
||||
|
||||
|
||||
//System.out.println();
|
||||
return count;
|
||||
}
|
||||
else{
|
||||
errarr[0]=true;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
69
cat.txt
Normal file
69
cat.txt
Normal file
@@ -0,0 +1,69 @@
|
||||
CAT(1) User Commands CAT(1)
|
||||
|
||||
NAME
|
||||
cat - concatenate files and print on the standard output
|
||||
|
||||
SYNOPSIS
|
||||
cat [OPTION]... [FILE]...
|
||||
|
||||
DESCRIPTION
|
||||
Concatenate FILE(s) to standard output.
|
||||
|
||||
With no FILE, or when FILE is -, read standard input.
|
||||
|
||||
-A, --show-all
|
||||
equivalent to -vET
|
||||
|
||||
-b, --number-nonblank
|
||||
number nonempty output lines, overrides -n
|
||||
|
||||
-e equivalent to -vE
|
||||
|
||||
-E, --show-ends
|
||||
display $ at end of each line
|
||||
|
||||
-n, --number
|
||||
number all output lines
|
||||
|
||||
-s, --squeeze-blank
|
||||
suppress repeated empty output lines
|
||||
|
||||
-t equivalent to -vT
|
||||
|
||||
-T, --show-tabs
|
||||
display TAB characters as ^I
|
||||
|
||||
-u (ignored)
|
||||
|
||||
-v, --show-nonprinting
|
||||
use ^ and M- notation, except for LFD and TAB
|
||||
|
||||
--help display this help and exit
|
||||
|
||||
--version
|
||||
output version information and exit
|
||||
|
||||
EXAMPLES
|
||||
cat f - g
|
||||
Output f's contents, then standard input, then g's contents.
|
||||
|
||||
cat Copy standard input to standard output.
|
||||
|
||||
AUTHOR
|
||||
Written by Torbjorn Granlund and Richard M. Stallman.
|
||||
|
||||
REPORTING BUGS
|
||||
GNU coreutils online help: <http://www.gnu.org/software/coreutils/>
|
||||
Report cat translation bugs to <http://translationproject.org/team/>
|
||||
|
||||
COPYRIGHT
|
||||
Copyright © 2017 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
|
||||
This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
|
||||
|
||||
SEE ALSO
|
||||
tac(1)
|
||||
|
||||
Full documentation at: <http://www.gnu.org/software/coreutils/cat>
|
||||
or available locally via: info '(coreutils) cat invocation'
|
||||
|
||||
GNU coreutils 8.28 January 2018 CAT(1)
|
||||
8
executeToCheck.java
Normal file
8
executeToCheck.java
Normal file
@@ -0,0 +1,8 @@
|
||||
import static cTools.KernelWrapper.*;
|
||||
|
||||
class executeToCheck {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Successfully sourced KernelWrapper!");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
3
java_use_me
Executable file
3
java_use_me
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
export LD_LIBRARY_PATH=./cTools
|
||||
/etc/alternatives/java $*
|
||||
Reference in New Issue
Block a user