chore: clean up
This commit is contained in:
140
GdBShell.java
140
GdBShell.java
@@ -29,17 +29,11 @@ public class GdBShell {
|
|||||||
|
|
||||||
|
|
||||||
String directoryPath = System.getProperty("user.dir");
|
String directoryPath = System.getProperty("user.dir");
|
||||||
String[] directoryArray = directoryPath.split("/");
|
directoryPath = directoryPath.replaceAll("^/home/\\w+", "~");
|
||||||
String str = "~";
|
|
||||||
|
|
||||||
|
|
||||||
//gets rid of the home/user directory and builds a string
|
|
||||||
for (int i = 3; (i < directoryArray.length); i++) {
|
|
||||||
str = str + "/" + directoryArray[i];
|
|
||||||
}
|
|
||||||
System.out.print("(" + runningInt + ")");
|
System.out.print("(" + runningInt + ")");
|
||||||
printColor(shellPrefix, "purple", false);
|
printColor(shellPrefix, AnsiColor.ANSI_PURPLE, false);
|
||||||
printColor(str + "$ ", "cyan", false);
|
printColor(directoryPath + "$ ", AnsiColor.ANSI_CYAN, false);
|
||||||
|
|
||||||
String input = scn.nextLine();//get input
|
String input = scn.nextLine();//get input
|
||||||
|
|
||||||
@@ -58,10 +52,10 @@ public class GdBShell {
|
|||||||
//implements the exit terminal function
|
//implements the exit terminal function
|
||||||
if (inputArray[0].equals("exit")) {
|
if (inputArray[0].equals("exit")) {
|
||||||
if (inputArray.length == 1) {
|
if (inputArray.length == 1) {
|
||||||
printColor("Session ended by user", "red", true);
|
printErr("Session ended by user");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
} else {
|
} else {
|
||||||
printColor("\"exit\" doesn't take parameters. It will end this current shell. Did you try to find a different executable?", "red", true);
|
printColor("\"exit\" doesn't take parameters. It will end this current shell. Did you try to find a different executable?", AnsiColor.ANSI_RED, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,12 +91,11 @@ public class GdBShell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevValue != 0 && singleCommand == false) {
|
if (prevValue != 0 && !singleCommand) {
|
||||||
printColor("Stopped concatenation at command number " + (i - 1) + " \"" + String.join(" ", commandsArr[i - 1]) + "\"", "red", true);
|
printErr("Stopped concatenation at command number " + (i - 1) + " \"" + String.join(" ", commandsArr[i - 1]) + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parseRedirect(String[] inputArray) {//should take pipe and read/write,, add >> for append?
|
static int parseRedirect(String[] inputArray) {//should take pipe and read/write,, add >> for append?
|
||||||
@@ -138,7 +131,7 @@ public class GdBShell {
|
|||||||
if (inputArray.length > redirectInPos + 1 && checkls(inputArray[redirectInPos + 1])) {
|
if (inputArray.length > redirectInPos + 1 && checkls(inputArray[redirectInPos + 1])) {
|
||||||
fd_in = open(inputArray[redirectInPos + 1], O_RDONLY);
|
fd_in = open(inputArray[redirectInPos + 1], O_RDONLY);
|
||||||
} else {
|
} else {
|
||||||
printColor("Error: Invalid input file path", "red", true);
|
printErr("Error: Invalid input file path");
|
||||||
return -1;
|
return -1;
|
||||||
}//throw error because invalid input file
|
}//throw error because invalid input file
|
||||||
}
|
}
|
||||||
@@ -148,7 +141,7 @@ public class GdBShell {
|
|||||||
fd_out = open(inputArray[redirectOutPos + 1], O_WRONLY | O_CREAT | O_TRUNC);//overwrite file if exists, create else
|
fd_out = open(inputArray[redirectOutPos + 1], O_WRONLY | O_CREAT | O_TRUNC);//overwrite file if exists, create else
|
||||||
|
|
||||||
if (inputArray.length <= redirectOutPos + 1) {
|
if (inputArray.length <= redirectOutPos + 1) {
|
||||||
printColor("Error: No output file specified after redirect output symbol", "red", true);
|
printErr("Error: No output file specified after redirect output symbol");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,7 +150,6 @@ public class GdBShell {
|
|||||||
int returnValue = parsePipe(command, fd_in, fd_out);
|
int returnValue = parsePipe(command, fd_in, fd_out);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -177,7 +169,7 @@ public class GdBShell {
|
|||||||
if (command.length > 1) {
|
if (command.length > 1) {
|
||||||
returnValue = pipe(pipe1fd);
|
returnValue = pipe(pipe1fd);
|
||||||
if (returnValue != 0) {
|
if (returnValue != 0) {
|
||||||
printColor("Error opening pipe", "red", true);
|
printErr("Error opening pipe");
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +178,7 @@ public class GdBShell {
|
|||||||
for (int i = 1; i < command.length - 1; i++) {
|
for (int i = 1; i < command.length - 1; i++) {
|
||||||
returnValue = pipe(pipe2fd);
|
returnValue = pipe(pipe2fd);
|
||||||
if (returnValue != 0) {
|
if (returnValue != 0) {
|
||||||
printColor("Error opening pipe", "red", true);
|
printErr("Error opening pipe");
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,18 +213,18 @@ public class GdBShell {
|
|||||||
if (inputArray.length > 0) {
|
if (inputArray.length > 0) {
|
||||||
|
|
||||||
String input = inputArray[0];
|
String input = inputArray[0];
|
||||||
|
|
||||||
path = which(input);//"/bin/"+input;
|
path = which(input);//"/bin/"+input;
|
||||||
//}
|
//}
|
||||||
} else {
|
} else {
|
||||||
printColor("Entered empty command", "red", true);
|
printErr("Entered empty command");
|
||||||
return -1;
|
return -1;
|
||||||
}// internal error code
|
}// internal error code
|
||||||
|
|
||||||
|
|
||||||
//if path found, compile argslist and start execv
|
//if path found, compile argslist and start execv
|
||||||
if (isNumeric(path) == false) {
|
if (!isNumeric(path)) {
|
||||||
printColor("Executing program at " + path, "green", true);
|
printColor("Executing program at " + path, AnsiColor.ANSI_GREEN, true);
|
||||||
|
|
||||||
int forkInt = fork();// saves the return value because every call will fork the process again
|
int forkInt = fork();// saves the return value because every call will fork the process again
|
||||||
|
|
||||||
@@ -253,7 +245,7 @@ public class GdBShell {
|
|||||||
|
|
||||||
//execute the program
|
//execute the program
|
||||||
if (execv(path, inputArray) < 0) {
|
if (execv(path, inputArray) < 0) {
|
||||||
printColor("execv fatal error", "red", true);
|
printErr("execv fatal error");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -264,7 +256,7 @@ public class GdBShell {
|
|||||||
//papa process
|
//papa process
|
||||||
else {
|
else {
|
||||||
if (forkInt < 0) {
|
if (forkInt < 0) {
|
||||||
printColor("Error: fork() returned Error", "red", true);
|
printErr("Error: fork() returned Error");
|
||||||
return forkInt;
|
return forkInt;
|
||||||
}
|
}
|
||||||
//close open files that only the child process needs
|
//close open files that only the child process needs
|
||||||
@@ -279,19 +271,19 @@ public class GdBShell {
|
|||||||
//wait for child
|
//wait for child
|
||||||
int f;
|
int f;
|
||||||
if ((f = waitpid(forkInt, intArray, 0)) < 0) {
|
if ((f = waitpid(forkInt, intArray, 0)) < 0) {
|
||||||
printColor("Error " + f + ": waiting for child", "red", true);
|
printErr("Error " + f + ": waiting for child");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (intArray[0] == 0) {
|
if (intArray[0] == 0) {
|
||||||
printColor("Process exited without error", "green", true);
|
printColor("Process exited without error", AnsiColor.ANSI_GREEN, true);
|
||||||
} else {
|
} else {
|
||||||
printColor("Process exited with error code " + intArray[0], "red", true);
|
printErr("Process exited with error code " + intArray[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printColor("Couldn't find executable assigned to \"" + inputArray[0] + "\"", "red", true);
|
printErr("Couldn't find executable assigned to \"" + inputArray[0] + "\"");
|
||||||
}
|
}
|
||||||
return intArray[0];
|
return intArray[0];
|
||||||
}
|
}
|
||||||
@@ -321,9 +313,8 @@ public class GdBShell {
|
|||||||
public static int greaterAbsolute(int a, int b) {
|
public static int greaterAbsolute(int a, int b) {
|
||||||
if (Math.abs(a) > Math.abs(b)) {
|
if (Math.abs(a) > Math.abs(b)) {
|
||||||
return a;
|
return a;
|
||||||
} else {
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -353,9 +344,9 @@ public class GdBShell {
|
|||||||
//System.out.println("\nExited with error code : " + exitCode);
|
//System.out.println("\nExited with error code : " + exitCode);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
printColor("err1", "red", true);
|
printErr("err1");
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
printColor("err2", "red", true);
|
printErr("err2");
|
||||||
}
|
}
|
||||||
|
|
||||||
return "t";
|
return "t";
|
||||||
@@ -364,7 +355,7 @@ public class GdBShell {
|
|||||||
|
|
||||||
public static boolean checkls(String input) {
|
public static boolean checkls(String input) {
|
||||||
|
|
||||||
|
|
||||||
String[] inputArray = input.split("/");
|
String[] inputArray = input.split("/");
|
||||||
String checkfile = inputArray[inputArray.length - 1];
|
String checkfile = inputArray[inputArray.length - 1];
|
||||||
StringBuffer buffer1 = new StringBuffer();
|
StringBuffer buffer1 = new StringBuffer();
|
||||||
@@ -379,7 +370,7 @@ public class GdBShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProcessBuilder prcBuilder = new ProcessBuilder();
|
ProcessBuilder prcBuilder = new ProcessBuilder();
|
||||||
prcBuilder.command("bash", "-c", "ls " + buffer1.toString());
|
prcBuilder.command("bash", "-c", "ls " + buffer1);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -405,9 +396,9 @@ public class GdBShell {
|
|||||||
//System.out.println("\nExited with error code : " + exitCode);
|
//System.out.println("\nExited with error code : " + exitCode);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
printColor("err1", "red", true);
|
printErr("err1");
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
printColor("err2", "red", true);
|
printErr("err2");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -426,59 +417,37 @@ public class GdBShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static boolean printColor(String text, String colorvar, boolean lineBreak) {// maybe rainbow??
|
enum AnsiColor {
|
||||||
//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)
|
ANSI_RESET("\u001B[0m"),
|
||||||
|
ANSI_BLACK("\u001B[30m"),
|
||||||
|
ANSI_RED("\u001B[31m"),
|
||||||
|
ANSI_YELLOW("\u001B[33m"),
|
||||||
|
ANSI_BLUE("\u001B[34m"),
|
||||||
|
ANSI_PURPLE("\u001B[35m"),
|
||||||
|
ANSI_CYAN("\u001B[36m"),
|
||||||
|
ANSI_WHITE("\u001B[37m"),
|
||||||
|
ANSI_GREEN("\u001B[32m");
|
||||||
|
private final String colorCode;
|
||||||
|
|
||||||
String ANSI_RESET = "\u001B[0m";
|
AnsiColor(String colorCode) {
|
||||||
String ANSI_BLACK = "\u001B[30m";
|
this.colorCode = colorCode;
|
||||||
String ANSI_RED = "\u001B[31m";
|
}
|
||||||
String ANSI_YELLOW = "\u001B[33m";
|
public String toString(){
|
||||||
String ANSI_BLUE = "\u001B[34m";
|
return this.colorCode;
|
||||||
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 = "";
|
|
||||||
|
|
||||||
switch (colorvar.toLowerCase()) {
|
|
||||||
case "white":
|
|
||||||
color = ANSI_WHITE;
|
|
||||||
break;
|
|
||||||
case "black":
|
|
||||||
color = ANSI_BLACK;
|
|
||||||
break;
|
|
||||||
case "red":
|
|
||||||
color = ANSI_RED;
|
|
||||||
break;
|
|
||||||
case "yellow":
|
|
||||||
color = ANSI_YELLOW;
|
|
||||||
break;
|
|
||||||
case "blue":
|
|
||||||
color = ANSI_BLUE;
|
|
||||||
break;
|
|
||||||
case "purple":
|
|
||||||
color = ANSI_PURPLE;
|
|
||||||
break;
|
|
||||||
case "cyan":
|
|
||||||
color = ANSI_CYAN;
|
|
||||||
break;
|
|
||||||
case "green":
|
|
||||||
color = ANSI_GREEN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
returnBool = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
System.out.print(color + text + ANSI_RESET);
|
}
|
||||||
|
static void printColor(String text, AnsiColor color, boolean lineBreak) {// maybe rainbow??
|
||||||
|
System.out.print(color + text + AnsiColor.ANSI_RESET);
|
||||||
|
|
||||||
if (lineBreak) {
|
if (lineBreak) {
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
return returnBool;
|
}
|
||||||
|
|
||||||
|
static void printErr(String text){
|
||||||
|
printColor(text, AnsiColor.ANSI_RED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String[] replaceCat(String[] args) {//used to integrate custom cat into shell
|
static String[] replaceCat(String[] args) {//used to integrate custom cat into shell
|
||||||
@@ -487,9 +456,8 @@ public class GdBShell {
|
|||||||
changed[0] = "java";
|
changed[0] = "java";
|
||||||
changed[1] = "cat.java";
|
changed[1] = "cat.java";
|
||||||
|
|
||||||
for (int i = 1; i < args.length; i++) {//ignore the "jcat" at first pos
|
//ignore the "jcat" at first pos
|
||||||
changed[i + 1] = args[i];
|
System.arraycopy(args, 1, changed, 2, args.length - 1);
|
||||||
}
|
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
} else {
|
} else {
|
||||||
@@ -500,4 +468,4 @@ public class GdBShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
44
cat.java
44
cat.java
@@ -15,7 +15,6 @@ public class cat{
|
|||||||
boolean[] errarr = {false};
|
boolean[] errarr = {false};
|
||||||
int count =0;
|
int count =0;
|
||||||
boolean [] params = parseArgs(args);//extract parameters and remove them from args
|
boolean [] params = parseArgs(args);//extract parameters and remove them from args
|
||||||
//System.out.println(Arrays.toString(args));//for testing
|
|
||||||
boolean argsnull=true;
|
boolean argsnull=true;
|
||||||
for(int i=0;i<args.length;i++){
|
for(int i=0;i<args.length;i++){
|
||||||
if(args[i]!=null){
|
if(args[i]!=null){
|
||||||
@@ -30,7 +29,6 @@ public class cat{
|
|||||||
|
|
||||||
//System.out.println(Arrays.toString(args));//for testing
|
//System.out.println(Arrays.toString(args));//for testing
|
||||||
if (params[0]){
|
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);
|
printFile("cat.txt",params,errarr,count);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -49,12 +47,6 @@ public class cat{
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
double end = System.nanoTime()-start;
|
|
||||||
end=end/(1000*1000*1000);
|
|
||||||
System.out.println(end);
|
|
||||||
*/
|
|
||||||
//System.out.println();
|
|
||||||
if(errarr[0]){System.exit(1);}
|
if(errarr[0]){System.exit(1);}
|
||||||
else{System.exit(0);}
|
else{System.exit(0);}
|
||||||
}
|
}
|
||||||
@@ -82,7 +74,6 @@ public class cat{
|
|||||||
int countEmpty=0;
|
int countEmpty=0;
|
||||||
boolean printThisLine = true;
|
boolean printThisLine = true;
|
||||||
while (true){
|
while (true){
|
||||||
|
|
||||||
try{
|
try{
|
||||||
String buf = scn.nextLine();
|
String buf = scn.nextLine();
|
||||||
|
|
||||||
@@ -91,7 +82,6 @@ public class cat{
|
|||||||
if(countEmpty>1){
|
if(countEmpty>1){
|
||||||
printThisLine = false;
|
printThisLine = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
countEmpty=0;
|
countEmpty=0;
|
||||||
@@ -99,12 +89,10 @@ public class cat{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(printThisLine){
|
if(printThisLine){
|
||||||
|
|
||||||
if(params[2]){
|
if(params[2]){
|
||||||
System.out.print("\u001B[33m"+"["+Integer.toString(count)+"]"+"\u001B[0m");
|
System.out.print("\u001B[33m"+"["+Integer.toString(count)+"]"+"\u001B[0m");
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println(buf);
|
System.out.println(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,10 +103,7 @@ public class cat{
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int printFile(String f, boolean[] params, boolean[] errarr, int count){
|
static int printFile(String f, boolean[] params, boolean[] errarr, int count){
|
||||||
|
|
||||||
|
|
||||||
//System.out.println(Arrays.toString(params));
|
//System.out.println(Arrays.toString(params));
|
||||||
int fd = open(f,O_RDONLY);
|
int fd = open(f,O_RDONLY);
|
||||||
int bufsz = Integer.MAX_VALUE/8; //test values?
|
int bufsz = Integer.MAX_VALUE/8; //test values?
|
||||||
@@ -132,29 +117,21 @@ public class cat{
|
|||||||
for (int i=0;i<rd;i++){
|
for (int i=0;i<rd;i++){
|
||||||
cleanbytes[i]= bytes[i];
|
cleanbytes[i]= bytes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String s = new String(cleanbytes, StandardCharsets.UTF_8);
|
String s = new String(cleanbytes, StandardCharsets.UTF_8);
|
||||||
String t = "";//length 0
|
String t = "";//length 0
|
||||||
String u = "";
|
String u = "";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(params[1]){//suppress multiple empty lines
|
if(params[1]){//suppress multiple empty lines
|
||||||
|
|
||||||
for (int i=0;i<s.length();i++){
|
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')){;}
|
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 = t+s.charAt(i);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{t=s;}
|
else{t=s;}
|
||||||
|
|
||||||
|
|
||||||
if(params[2]){//enumerate lines
|
if(params[2]){//enumerate lines
|
||||||
u = u + "\u001B[33m"+"["+Integer.toString(count)+"]"+"\u001B[0m";
|
u = u + "\u001B[33m"+"["+Integer.toString(count)+"]"+"\u001B[0m";
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
for (int i=0;i<t.length();i++){
|
for (int i=0;i<t.length();i++){
|
||||||
u = u + t.charAt(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
|
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
|
||||||
@@ -163,7 +140,6 @@ public class cat{
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else{u=t;}
|
else{u=t;}
|
||||||
|
|
||||||
@@ -173,30 +149,12 @@ public class cat{
|
|||||||
u = u+ '\n';
|
u = u+ '\n';
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
System.out.print(u);
|
System.out.print(u);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//System.out.println();
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
errarr[0]=true;
|
errarr[0]=true;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user