// File: sanaa-khan[P]mini-linux-shell/gbsh.cpp
// Function: main
int main(int argc, char *argv[]) {

	signal(SIGINT, handle_signal); // program will ignore ctrl+c

	int len = 50;
	char host[len], user[len], cwd[len];
	string command;

	gethostname(host, len);
	getlogin_r(user, len);

	while (true) {
		getcwd(cwd, len);
		cout << "\033[1;36m" << user << "@" << host << "\033[0m";
		cout << "\033[1;35m " << cwd << "\033[0m > ";
		
		getline(cin, command);

		if (command == "exit") {
			exit(0);
		}

		else if (command == "clear")
			cout << "\033c";

		// building vector of commands
		else {
			vector<string> tokens;
			string temp;

			for (int i = 0; i < command.size(); i++) {

				while (command[i] != ' ' and command[i] != '\n' and command[i] != '\t' and command[i] != '\0') {
					temp += command[i];
					i++;
				}

				tokens.push_back(temp);
				temp = "";
			}

			displayVector(tokens);

			string cmd = tokens.front();

			if (cmd == "ls")
				listDirectory(tokens);

			else if (cmd == "pwd")
				printWorkingDirectory(tokens);

			else if (cmd == "cd") 
				changeDirectory(tokens);

			else if (cmd == "environ")
				listEnvVars(tokens);

			else if (cmd == "setenv")
				setEnvVar(tokens);

			else if (cmd == "unsetenv")
				unsetEnvVar(tokens);

			else {
				bool background = false;

				// for background execution
				if (tokens[tokens.size() - 1].size() == 1 and tokens[tokens.size() - 1][0] == '&') {
					background = true;
					tokens.pop_back();
				}

				bool skip = false;

				/// detecting pipe
				for (int i = 0; i < tokens.size(); i++) {
					if (tokens[i].size() == 1 and tokens[i][0] == '|') {
						pipeCommands(tokens);
						skip = true;
					}
				}

				if (!skip) {
					pid_t pid = fork();

					if (pid > 0) { // parent process
						if (!background)
							waitpid(pid, 0, 0); // wait until child of pid is terminated

						if (oRedirect) { // redirect output back to stdout 
							fflush(stdout); 

							dup2(output, 1);
							close(output);

							oRedirect = false;
						}

						if (iRedirect) { // redirect input back to stdin
							fflush(stdin); 

							dup2(input, 0);
							close(input);

							iRedirect = false;
						}
					}

					else if (pid == 0) { // child process
						setenv("SHELL", cwd, 1);
						executeProgram(tokens);
					}

					else
						cout << "Fork unsuccessful";
				}
			}

			tokens.clear();

			pid_t anyChild = 1;

			while (anyChild > 0) { // reaping zombie processes (that may have been running in background previously)
				anyChild = waitpid(-1, 0, WNOHANG);
			}
		} 
	}

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x270, %rsp            # imm = 0x270
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x30(%rip), %rsi       # 0x2490
movl $0x2, %edi
callq 0x21f0
movl $0x32, -0x14(%rbp)
movl -0x14(%rbp), %eax
movq %rsp, %rcx
movq %rcx, -0x20(%rbp)
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1c8(%rbp)
movq %rcx, %rsp
movq %rax, -0x28(%rbp)
movl -0x14(%rbp), %eax
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1c0(%rbp)
movq %rcx, %rsp
movq %rax, -0x30(%rbp)
movl -0x14(%rbp), %eax
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1d0(%rbp)
movq %rcx, %rsp
movq %rax, -0x38(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x2260
movq -0x1c8(%rbp), %rdi
movslq -0x14(%rbp), %rsi
callq 0x2290
movq -0x1c0(%rbp), %rdi
movslq -0x14(%rbp), %rsi
callq 0x2310
jmp 0x2569
jmp 0x256b
jmp 0x256d
movq -0x1d0(%rbp), %rdi
movslq -0x14(%rbp), %rsi
callq 0x20d0
movq 0x7a44(%rip), %rdi      # 0x9fc8
leaq 0x4a79(%rip), %rsi      # 0x7004
callq 0x21b0
movq %rax, -0x1d8(%rbp)
jmp 0x2599
movq -0x1c0(%rbp), %rsi
movq -0x1d8(%rbp), %rdi
callq 0x21b0
movq %rax, -0x1e0(%rbp)
jmp 0x25b5
movq -0x1e0(%rbp), %rdi
leaq 0x4a49(%rip), %rsi      # 0x700c
callq 0x21b0
movq %rax, -0x1e8(%rbp)
jmp 0x25d1
movq -0x1c8(%rbp), %rsi
movq -0x1e8(%rbp), %rdi
callq 0x21b0
movq %rax, -0x1f0(%rbp)
jmp 0x25ed
movq -0x1f0(%rbp), %rdi
leaq 0x4a13(%rip), %rsi      # 0x700e
callq 0x21b0
jmp 0x2602
movq 0x79bf(%rip), %rdi      # 0x9fc8
leaq 0x4a03(%rip), %rsi      # 0x7013
callq 0x21b0
movq %rax, -0x1f8(%rbp)
jmp 0x261e
movq -0x1d0(%rbp), %rsi
movq -0x1f8(%rbp), %rdi
callq 0x21b0
movq %rax, -0x200(%rbp)
jmp 0x263a
movq -0x200(%rbp), %rdi
leaq 0x49d4(%rip), %rsi      # 0x701c
callq 0x21b0
jmp 0x264f
movq 0x798a(%rip), %rdi      # 0x9fe0
leaq -0x58(%rbp), %rsi
callq 0x2050
jmp 0x2661
leaq 0x49bc(%rip), %rsi      # 0x7024
leaq -0x58(%rbp), %rdi
callq 0x54b0
movb %al, -0x201(%rbp)
jmp 0x2679
movb -0x201(%rbp), %al
testb $0x1, %al
jne 0x2685
jmp 0x269d
xorl %edi, %edi
callq 0x2200
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x2f1b
leaq 0x4985(%rip), %rsi      # 0x7029
leaq -0x58(%rbp), %rdi
callq 0x54b0
movb %al, -0x202(%rbp)
jmp 0x26b5
movb -0x202(%rbp), %al
testb $0x1, %al
jne 0x26c1
jmp 0x26db
movq 0x7900(%rip), %rdi      # 0x9fc8
leaq 0x4960(%rip), %rsi      # 0x702f
callq 0x21b0
jmp 0x26d6
jmp 0x2f14
leaq -0x80(%rbp), %rdi
callq 0x54e0
leaq -0xa0(%rbp), %rdi
callq 0x2260
movl $0x0, -0xa4(%rbp)
movslq -0xa4(%rbp), %rax
movq %rax, -0x210(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x2120
movq %rax, %rcx
movq -0x210(%rbp), %rax
cmpq %rcx, %rax
jae 0x2888
jmp 0x2726
movslq -0xa4(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x2340
movq %rax, -0x218(%rbp)
jmp 0x273f
movq -0x218(%rbp), %rax
movsbl (%rax), %ecx
xorl %eax, %eax
cmpl $0x20, %ecx
movb %al, -0x219(%rbp)
je 0x27e9
movslq -0xa4(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x2340
movq %rax, -0x228(%rbp)
jmp 0x2773
movq -0x228(%rbp), %rax
movsbl (%rax), %ecx
xorl %eax, %eax
cmpl $0xa, %ecx
movb %al, -0x219(%rbp)
je 0x27e9
movslq -0xa4(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x2340
movq %rax, -0x230(%rbp)
jmp 0x27a3
movq -0x230(%rbp), %rax
movsbl (%rax), %ecx
xorl %eax, %eax
cmpl $0x9, %ecx
movb %al, -0x219(%rbp)
je 0x27e9
movslq -0xa4(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x2340
movq %rax, -0x238(%rbp)
jmp 0x27d3
movq -0x238(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
setne %al
movb %al, -0x219(%rbp)
movb -0x219(%rbp), %al
testb $0x1, %al
jne 0x27f5
jmp 0x284b
movslq -0xa4(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x2340
movq %rax, -0x240(%rbp)
jmp 0x280e
movq -0x240(%rbp), %rax
movsbl (%rax), %esi
leaq -0xa0(%rbp), %rdi
callq 0x2110
jmp 0x2826
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x2726
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x2efd
leaq -0x80(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x5500
jmp 0x285d
leaq 0x484c(%rip), %rsi      # 0x70b0
leaq -0xa0(%rbp), %rdi
callq 0x2240
jmp 0x2872
jmp 0x2874
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x26fa
leaq -0xc0(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x289a
leaq -0xc0(%rbp), %rdi
callq 0x5570
jmp 0x28a8
leaq -0xc0(%rbp), %rdi
callq 0x56d0
leaq -0x80(%rbp), %rdi
callq 0x5730
movq %rax, %rsi
leaq -0xe0(%rbp), %rdi
callq 0x20c0
jmp 0x28ce
leaq 0x475d(%rip), %rsi      # 0x7032
leaq -0xe0(%rbp), %rdi
callq 0x54b0
movb %al, -0x241(%rbp)
jmp 0x28e9
movb -0x241(%rbp), %al
testb $0x1, %al
jne 0x28f5
jmp 0x2971
leaq -0xf8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x2907
leaq -0xf8(%rbp), %rdi
callq 0x2f30
jmp 0x2915
leaq -0xf8(%rbp), %rdi
callq 0x56d0
jmp 0x2e89
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x56d0
jmp 0x2efd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x2ef1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
leaq 0x46bd(%rip), %rsi      # 0x7035
leaq -0xe0(%rbp), %rdi
callq 0x54b0
movb %al, -0x242(%rbp)
jmp 0x298c
movb -0x242(%rbp), %al
testb $0x1, %al
jne 0x2998
jmp 0x29e6
leaq -0x110(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x29aa
leaq -0x110(%rbp), %rdi
callq 0x3830
jmp 0x29b8
leaq -0x110(%rbp), %rdi
callq 0x56d0
jmp 0x2e87
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
leaq 0x464c(%rip), %rsi      # 0x7039
leaq -0xe0(%rbp), %rdi
callq 0x54b0
movb %al, -0x243(%rbp)
jmp 0x2a01
movb -0x243(%rbp), %al
testb $0x1, %al
jne 0x2a0d
jmp 0x2a5b
leaq -0x128(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x2a1f
leaq -0x128(%rbp), %rdi
callq 0x3aa0
jmp 0x2a2d
leaq -0x128(%rbp), %rdi
callq 0x56d0
jmp 0x2e85
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x128(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
leaq 0x45da(%rip), %rsi      # 0x703c
leaq -0xe0(%rbp), %rdi
callq 0x54b0
movb %al, -0x244(%rbp)
jmp 0x2a76
movb -0x244(%rbp), %al
testb $0x1, %al
jne 0x2a82
jmp 0x2ad0
leaq -0x140(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x2a94
leaq -0x140(%rbp), %rdi
callq 0x3bc0
jmp 0x2aa2
leaq -0x140(%rbp), %rdi
callq 0x56d0
jmp 0x2e83
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
leaq 0x456f(%rip), %rsi      # 0x7046
leaq -0xe0(%rbp), %rdi
callq 0x54b0
movb %al, -0x245(%rbp)
jmp 0x2aeb
movb -0x245(%rbp), %al
testb $0x1, %al
jne 0x2af7
jmp 0x2b45
leaq -0x158(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x2b09
leaq -0x158(%rbp), %rdi
callq 0x3fb0
jmp 0x2b17
leaq -0x158(%rbp), %rdi
callq 0x56d0
jmp 0x2e81
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
leaq 0x44f8(%rip), %rsi      # 0x7044
leaq -0xe0(%rbp), %rdi
callq 0x54b0
movb %al, -0x246(%rbp)
jmp 0x2b60
movb -0x246(%rbp), %al
testb $0x1, %al
jne 0x2b6c
jmp 0x2bba
leaq -0x170(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x2b7e
leaq -0x170(%rbp), %rdi
callq 0x4290
jmp 0x2b8c
leaq -0x170(%rbp), %rdi
callq 0x56d0
jmp 0x2e7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x170(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
movb $0x0, -0x171(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x5780
movq %rax, %rsi
subq $0x1, %rsi
leaq -0x80(%rbp), %rdi
callq 0x5760
movq %rax, %rdi
callq 0x2120
cmpq $0x1, %rax
jne 0x2c3e
leaq -0x80(%rbp), %rdi
movq %rdi, -0x258(%rbp)
callq 0x5780
movq -0x258(%rbp), %rdi
movq %rax, %rsi
decq %rsi
callq 0x5760
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2340
movq %rax, -0x250(%rbp)
jmp 0x2c1f
movq -0x250(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x26, %eax
jne 0x2c3e
movb $0x1, -0x171(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x57a0
movb $0x0, -0x172(%rbp)
movl $0x0, -0x178(%rbp)
movslq -0x178(%rbp), %rax
movq %rax, -0x260(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x5780
movq %rax, %rcx
movq -0x260(%rbp), %rax
cmpq %rcx, %rax
jae 0x2d37
movslq -0x178(%rbp), %rsi
leaq -0x80(%rbp), %rdi
callq 0x5760
movq %rax, %rdi
callq 0x2120
cmpq $0x1, %rax
jne 0x2d21
movslq -0x178(%rbp), %rsi
leaq -0x80(%rbp), %rdi
callq 0x5760
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2340
movq %rax, -0x268(%rbp)
jmp 0x2cc0
movq -0x268(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x7c, %eax
jne 0x2d21
leaq -0x190(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x2ce1
leaq -0x190(%rbp), %rdi
callq 0x44e0
jmp 0x2cef
leaq -0x190(%rbp), %rdi
callq 0x56d0
movb $0x1, -0x172(%rbp)
jmp 0x2d21
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x190(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
jmp 0x2d23
movl -0x178(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x178(%rbp)
jmp 0x2c4f
testb $0x1, -0x172(%rbp)
jne 0x2e7d
callq 0x2060
movl %eax, -0x194(%rbp)
cmpl $0x0, -0x194(%rbp)
jle 0x2df6
testb $0x1, -0x171(%rbp)
jne 0x2d78
movl -0x194(%rbp), %edi
xorl %edx, %edx
movl %edx, %esi
callq 0x2160
jmp 0x2d76
jmp 0x2d78
testb $0x1, 0x7451(%rip)      # 0xa1d0
je 0x2db6
movq 0x7220(%rip), %rax      # 0x9fa8
movq (%rax), %rdi
callq 0x21e0
jmp 0x2d92
movl 0x7430(%rip), %edi      # 0xa1c8
movl $0x1, %esi
callq 0x2190
movl 0x7420(%rip), %edi      # 0xa1c8
callq 0x2330
jmp 0x2daf
movb $0x0, 0x741a(%rip)      # 0xa1d0
testb $0x1, 0x7414(%rip)      # 0xa1d1
je 0x2df1
movq 0x71fa(%rip), %rax      # 0x9fc0
movq (%rax), %rdi
callq 0x21e0
jmp 0x2dd0
movl 0x73f6(%rip), %edi      # 0xa1cc
xorl %esi, %esi
callq 0x2190
movl 0x73e9(%rip), %edi      # 0xa1cc
callq 0x2330
jmp 0x2dea
movb $0x0, 0x73e0(%rip)      # 0xa1d1
jmp 0x2e7b
cmpl $0x0, -0x194(%rbp)
jne 0x2e62
movq -0x1d0(%rbp), %rsi
leaq 0x4240(%rip), %rdi      # 0x704d
movl $0x1, %edx
callq 0x22b0
leaq -0x1b0(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x55e0
jmp 0x2e29
leaq -0x1b0(%rbp), %rdi
callq 0x46b0
jmp 0x2e37
leaq -0x1b0(%rbp), %rdi
callq 0x56d0
jmp 0x2e79
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x56d0
jmp 0x2ef1
movq 0x715f(%rip), %rdi      # 0x9fc8
leaq 0x41e3(%rip), %rsi      # 0x7053
callq 0x21b0
jmp 0x2e77
jmp 0x2e79
jmp 0x2e7b
jmp 0x2e7d
jmp 0x2e7f
jmp 0x2e81
jmp 0x2e83
jmp 0x2e85
jmp 0x2e87
jmp 0x2e89
leaq -0x80(%rbp), %rdi
callq 0x57d0
movl $0x1, -0x1b4(%rbp)
cmpl $0x0, -0x1b4(%rbp)
jle 0x2ece
xorl %eax, %eax
movl %eax, %esi
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movl $0x1, %edx
callq 0x2160
movl %eax, -0x26c(%rbp)
jmp 0x2ec0
movl -0x26c(%rbp), %eax
movl %eax, -0x1b4(%rbp)
jmp 0x2e9c
leaq -0xe0(%rbp), %rdi
callq 0x2100
leaq -0xa0(%rbp), %rdi
callq 0x2100
leaq -0x80(%rbp), %rdi
callq 0x56d0
jmp 0x2f14
leaq -0xe0(%rbp), %rdi
callq 0x2100
leaq -0xa0(%rbp), %rdi
callq 0x2100
leaq -0x80(%rbp), %rdi
callq 0x56d0
jmp 0x2f1b
jmp 0x2f16
jmp 0x256b
leaq -0x58(%rbp), %rdi
callq 0x2100
movq -0x60(%rbp), %rdi
callq 0x2320
nopl (%rax)