22void report_error_code(
int code) {
52void get_cwd(
unsigned int buffer_size, os_char *buffer) {
53 if(!getcwd(buffer, buffer_size)) {
59 int error_code = chdir(new_dir);
63 report_error_code(errno);
68 printf(
"\e[1;1H\e[2J");
72 const int status = unlink(filename);
77 report_error_code(errno);
81bool lsdir(
const char *dir) {
82 struct dirent *de = NULL;
83 DIR *dr = opendir(dir);
84 int entries_count = 0;
90 while((de = readdir(dr)) != NULL) {
91 if(de->d_type == DT_DIR)
93 else if(de->d_type == DT_REG)
100 if(entries_count > 0)
108void handle_background_child_exit(
int sig) {
110 waitpid(-1, &stat, WNOHANG);
115 assert(
args.
argc > 0 &&
"Invalid args");
116 struct args copied_args;
121 report_error_code(errno);
127 signal(SIGINT, SIG_DFL);
128 if(execvp(copied_args.argv[0], copied_args.argv) == -1) {
129 report_error_code(errno);
135 waitpid(pid, &stat_loc, 0);
137 signal(SIGCHLD, handle_background_child_exit);
140 if(WIFEXITED(stat_loc)) {
141 const int exit_code = WEXITSTATUS(stat_loc);
147 }
else if(WIFSTOPPED(stat_loc)) {
150 }
else if(WCOREDUMP(stat_loc)) {
153 }
else if(WIFSIGNALED(stat_loc)) {
154 if(WTERMSIG(stat_loc) == SIGSEGV) {
175 const int res = setenv(name, val == NULL ?
"" : val,
true);
179 report_error_code(errno);
184 const int res = unsetenv(name);
188 report_error_code(errno);
192bool get_shell_env(
const os_char *var,
unsigned int buffer_size, os_char *buffer) {
193 const os_char *res = getenv(var);
198 const unsigned int len = strlen(res);
199 if(len >= buffer_size) {
203 memcpy(buffer, res, len);
209 return getenv(var) != NULL;
214 unsigned int len = 0;
217 for(
int i = 0; *(environ + i) != NULL; ++i) {
218 const os_char *var = *(environ + i);
219 const unsigned int var_len = strlen(var);
220 const unsigned int new_len = len + 1 + var_len;
221 while(new_len >= reserve_len) {
223 os_char *new_res = realloc(res, reserve_len);
226 format_error(
"Cannot allocate enough memory to copy environment variables\n");
231 memcpy(res + len, var, var_len);
233 res[new_len - 1] =
'\n';
241 struct dirent *entry = NULL;
245 procdir = opendir(
"/proc");
246 if(procdir == NULL) {
248 report_error_code(errno);
253 while((entry = readdir(procdir)) != NULL) {
258 snprintf(path,
sizeof(path),
"/proc/%s/status", entry->d_name);
260 FILE *statusfile = fopen(path,
"r");
261 if(statusfile == NULL) {
264# define NAME_LENGTH 512
265 char name[NAME_LENGTH];
267 if(fscanf(statusfile,
"Name: %s512\n", name) != 1) {
272 pid_t pid = atoi(entry->d_name);
274 char line[NAME_LENGTH];
277 while(fgets(line,
sizeof(line), statusfile) != NULL) {
279 if(strncmp(line,
"PPid:", 5) == 0) {
280 sscanf(line + 5,
"%d", &ppid);
286 DIR *t_procdir = NULL;
287 char thread_count[3];
288 snprintf(path,
sizeof path,
"/proc/%d/task", pid);
289 t_procdir = opendir(path);
291 if(t_procdir == NULL) {
292 thread_count[0] =
'?';
293 thread_count[1] =
'\0';
295 unsigned int t_count = 0;
296 struct dirent *entry = NULL;
298 while((entry = readdir(t_procdir)) != NULL) {
303 snprintf(thread_count,
sizeof thread_count,
"%d", t_count);
307 printf(
"PID: %6u PPID: %6u T %3s Name: %s \n", pid, ppid, thread_count, name);
315 enum { buffer_size = 300 };
316 os_char *buffer = malloc(buffer_size *
sizeof(os_char));
317 if(readlink(
"/proc/self/exe", buffer, buffer_size) == -1) {
318 report_error_code(errno);
324 struct args *mod = malloc(
sizeof(
struct args));
327 mod->
argv = malloc((mod->
argc + 1) *
sizeof(os_char *));
329 mod->
argv[0] = buffer;
331 mod->
argv[1] = malloc(3 *
sizeof(os_char));
332 memcpy(mod->
argv[1],
"-f", 2);
333 mod->
argv[1][2] =
'\0';
335 for(
int i = count; i < mod->
argc; ++i) {
336 const unsigned int len = strlen(
args.
argv[i - count]);
337 mod->
argv[i] = malloc((len + 1) *
sizeof(os_char));
339 mod->
argv[i][len] =
'\0';
348bool check_process_exist(
int proc_id) {
349 const bool exists = kill(proc_id, 0) == 0;
351 report_error_code(errno);
358 DIR *dir = opendir(
"/proc");
363 struct dirent *entry = NULL;
367 int countChildProcess = 0;
370 while((entry = readdir(dir)) != NULL) {
371 if(entry->d_type == DT_DIR &&
is_number(entry->d_name)) {
372 snprintf(path_buffer,
sizeof(path_buffer),
"/proc/%s/stat", entry->d_name);
373 fp = fopen(path_buffer,
"r");
382 if(fscanf(fp,
"%d %s %c %d", &pid, comm, &state, &ppid) != 4) {
388 if(ppid == proc_id) {
390 snprintf(path_buffer,
sizeof(path_buffer),
"/proc/%d/status", pid);
391 fp = fopen(path_buffer,
"r");
395 while(fgets(line,
sizeof(line), fp)) {
396 if(sscanf(line,
"Threads: %d", &threads) == 1) {
403 comm[strlen(comm) - 1] =
'\0';
404 format_success(
"PID: %6d T: %3d Name: %s \n", pid, threads, comm + 1);
412 if(countChildProcess == 0) {
421 const time_t current_time = time(NULL);
422 struct tm *local_time = localtime(¤t_time);
423 const int initial_year = 1900;
424 format_output(
"The current date is: %02d/%02d/%04d.\n", local_time->tm_mday, local_time->tm_mon + 1, local_time->tm_year + initial_year);
430 const time_t current_time = time(NULL);
431 struct tm *local_time = localtime(¤t_time);
432 format_output(
"The current time is: %02d:%02d:%02d.\n", local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
437 if(!check_process_exist(proc_id)) {
440 if(kill(proc_id, SIGTERM) == 0) {
444 report_error_code(errno);
445 format_error(
"Can't terminate process with id %d\n.", proc_id);
450 if(!check_process_exist(proc_id))
452 if(kill(proc_id, SIGCONT) == 0) {
456 report_error_code(errno);
457 format_error(
"Can't resume process with id %d\n.", proc_id);
462 if(!check_process_exist(proc_id))
464 if(kill(proc_id, SIGSTOP) == 0) {
468 report_error_code(errno);
469 format_error(
"Can't stop process with id %d\n.", proc_id);
void args_deep_copy_init(struct args *obj, const struct args *source)
Initialize the object by deep copying source
void args_destroy(struct args *obj)
#define TIME_DATE_BUFFER_SIZE
#define ENVS_RESERVE_SIZE
void format_output(char *fmt,...)
Used format_xxx instead of printf and such for uniform output.
void format_success(char *fmt,...)
Used format_xxx instead of printf and such for uniform output.
void format_error(char *fmt,...)
Used format_xxx instead of printf and such for uniform output.
bool stop_proccess(int proc_id)
Stop a process use it ID.
bool get_date()
Get current date.
bool has_shell_env(const os_char *var)
Check if a variable environment exists.
bool change_cwd(const os_char *new_dir)
Attempt to change current working directory.
bool get_shell_env(const os_char *var, unsigned int buffer_size, os_char *buffer)
Get value of an an environment variable.
void clear_screen()
Clear the console.
bool kill_process(int proc_id)
Kill a process.
bool show_child_processes(int proc_id)
Show child processes.
bool enum_proc()
List all running processes.
bool lsdir(const os_char *dir)
List of files or folders in specific directory.
bool minibat(const struct args args)
Launch shell executable and execute the file specified by args.argv[0]
os_char * get_all_shell_env_display()
Get all current environment variable.
bool delete_file(const os_char *filename)
Delete a specific file.
bool set_shell_env(const os_char *name, const os_char *val)
Set environment variable of the shell process.
bool launch_executable(const struct args args)
Launch the executable.
bool get_time()
Get current time.
bool unset_shell_env(const os_char *name)
Unset environment variable of the shell process.
void get_cwd(unsigned int buffer_size, os_char *buffer)
Fetch current working directory and copy them into buffer
bool resume(int proc_id)
Resume running a process.
Result after parsing an arbitrary string.
bool is_number(const char *c)