#include "file_open.h" #include "file_access.h" #include #include #include #include #include "nonblocking_io.h" #include "serialize_lock.h" static opened_file_state_t opened_file_create() { opened_file_state_t state = { .error = FILOPER_SUCCESS, .ended_with_error = false, .executed = false, .type = 0, }; return state; } static void file_prepare_before_open() { serialize_unlock(); } static void file_prepare_after_close() { struct termios old; file_set_nonblocking(STDIN_FILENO, &old); if (serialize_lock(1) <= 0) { serialize_lock(0); } } static opened_file_state_t file_execute(executing_file_t *executing, opened_type_t type) { executing_file_wait(executing); file_prepare_after_close(); opened_file_state_t opened = opened_file_create(); opened.type = type; opened.executed = true; opened.executing_file = *executing; opened.ended_with_error = executing->output_signal != 0; return opened; } static opened_file_state_t file_open_mime(file_t *file, exec_options_t *options, fileaccess_state_t state, char *base_mime) { opened_file_state_t opened = opened_file_create(); if (options == NULL) { return opened; } char mime[256]; if (base_mime != NULL) { strcpy(mime, base_mime); } else { opened.error = fileaccess_file_get_mimetype(state, file, mime); if (opened.error != FILOPER_SUCCESS) { return opened; } } char *program = exec_options_get_program(options, mime); if (program == NULL) { return opened; } char local_path[PATH_MAX]; opened.error = fileaccess_file_get_local_path(state, file, local_path); if (opened.error != FILOPER_SUCCESS) { return opened; } file_prepare_before_open(); executing_file_error_t executing_or_error = executing_file_execute(program, local_path); if (executing_or_error.error != FILOPER_SUCCESS) { opened.error = executing_or_error.error; return opened; } return file_execute(&executing_or_error.file, base_mime != NULL ? OPENED_TEXT : OPENED_MIME); } static opened_file_state_t file_open_text(file_t *file, exec_options_t *options, fileaccess_state_t state) { return file_open_mime(file, options, state, "text"); } static opened_file_state_t file_open_executable(file_t *file, exec_options_t *options, fileaccess_state_t state) { opened_file_state_t opened = opened_file_create(); if (file->permissions & S_IEXEC) { // executable file_prepare_before_open(); executing_file_or_error_t executing_or_error = fileaccess_file_execute(state, file, ""); if (executing_or_error.error) { opened.error = executing_or_error.error; return opened; } return file_execute(&executing_or_error.payload.file, OPENED_EXEC); } return opened; } opened_file_state_t file_open(file_t *file, exec_options_t *options, fileaccess_state_t state) { opened_file_state_t opened; // 1. try mime opened = file_open_mime(file, options, state, NULL); if (opened.executed || opened.error != FILOPER_SUCCESS) { return opened; } // 2. is executable? execute it opened = file_open_executable(file, options, state); if (opened.executed || opened.error != FILOPER_SUCCESS) { return opened; } // 3. text mime return file_open_text(file, options, state); }