Internal implementation of cd
[minishell-2.git] / Sources / opsys.cpp
blob71651b93e613a7d13021025ef26ebcecf8d7808c
1 #include "Headers/opsys.h"
3 #include <sys/param.h> // MAXPATHLEN
4 #include <sys/wait.h> // waitpid
5 #include <unistd.h> // getcwd, fork, chdir, geuid, gethostname, execvp
6 #include <pwd.h> // struct passwd, getpwuid_r
8 using std::cin;
9 using std::cout;
10 using std::cerr;
12 OpSys OS; // Global OpSys variable. Should be accessible to all modules.
13 bool exit_program = false;
15 void signal_handler(int s)
17 if (s==SIGINT)
19 cout << "\nSIGINT (Ctrl+C) received. Code " << s << ". Exiting.\n";
20 exit_program = true; // We'll do this instead of an exit(0) in order to allow for cleanup.
23 if (s==SIGHUP)
25 cout << "\nSIGHUP received. Code " << s << ". Exiting.\n";
26 exit_program = true; // We'll do this instead of an exit(0) in order to allow for cleanup.
30 SignalHandler::SignalHandler()
32 signal_action.sa_handler = signal_handler;
33 sigemptyset(&signal_action.sa_mask);
34 signal_action.sa_flags = 0;
35 sigaction(SIGINT, &signal_action, NULL);
38 string OpSys::get_cwd()
40 char temp[MAXPATHLEN];
41 return getcwd(temp, sizeof(temp)) ? std::string( temp ) : std::string("");
44 void OpSys::change_dir(vector<string> command)
46 if (command.size() == 1 || !command[1].compare("~") || !command[1].compare("$HOME"))
47 { // User wants to cd into $HOME/~.
48 chdir(getenv("HOME"));
49 this->cwd = get_cwd();
50 cwd_changed = true;
51 return;
54 string cmd;
56 for(unsigned short int i = 1; i < command.size(); i++) // TODO: unneeded?
57 cmd += command[i];
59 if (chdir(cmd.c_str()))
61 // Couldn't get to change dirs
62 cerr << "minish2: cd: " << cmd << ": Arquivo ou diretório não encontrado.\n";
64 else
66 // chdir worked. and tell Prompt to act accordingly.
67 this->cwd = get_cwd(); // Update the OpSys OS's current cwd
68 cwd_changed = true; // Signals a cwd change to Prompt.
72 vector<const char*> make_argv(vector<string>const& in)
74 vector<const char*> out;
75 out.reserve(in.size() + 1);
76 for (const auto& s : in)
77 out.push_back(s.data());
78 out.push_back(nullptr);
79 out.shrink_to_fit();
80 return out;
83 short OpSys::simple_command(vector<string> tokens)
85 int status;
86 if(is_verbose)
88 cerr << "execvp(\"" << tokens[0] << "\",\"";
89 for(unsigned int i = 0; i < tokens.size()-1; i++)
90 cerr << tokens[i] << ' ';
91 cerr << tokens.back();
92 cerr << "\");\n";
96 pid_t pid = fork();
97 if (pid == 0)
99 execvp(tokens[0].c_str(), const_cast<char* const *>(make_argv(tokens).data()));
100 cerr << tokens[0] << ": command not found.\n";
101 return 0; // TODO: exit with cleanup
103 else if (pid < 0)
105 printf("Couldn't fork a process.");
106 return 0;
108 waitpid(-1, &status, WUNTRACED);
109 return 1;
112 OpSys::OpSys()
114 cwd = get_cwd();
115 if(cwd.empty())
116 cerr << RED_ANSI << "Could not get the current working directory.\n" << RESET_ANSI;
118 uid_t uid = geteuid(); // Gets the effective ID of the user that started miniSHELL
119 struct passwd pwent;
120 struct passwd *pwent_ptr;
121 char buffer[1024];
123 // Looks for the UDI on the password databank and saves the result on pwent
124 getpwuid_r(uid, &pwent, buffer, sizeof buffer, &pwent_ptr);
125 username = pwent.pw_name; // Saves username
127 char hostname[64];
128 gethostname(hostname, 64);
129 this->hostname = hostname;