1c0abf9e6Sopenharmony_ci// SPDX-License-Identifier: MIT 2c0abf9e6Sopenharmony_ci/* 3c0abf9e6Sopenharmony_ci * Copyright © 2013 Red Hat, Inc. 4c0abf9e6Sopenharmony_ci */ 5c0abf9e6Sopenharmony_ci 6c0abf9e6Sopenharmony_ci#include "config.h" 7c0abf9e6Sopenharmony_ci#include <check.h> 8c0abf9e6Sopenharmony_ci#include <errno.h> 9c0abf9e6Sopenharmony_ci#include <stdio.h> 10c0abf9e6Sopenharmony_ci#include <stdlib.h> 11c0abf9e6Sopenharmony_ci#include <unistd.h> 12c0abf9e6Sopenharmony_ci#include <sys/ptrace.h> 13c0abf9e6Sopenharmony_ci#include <sys/resource.h> 14c0abf9e6Sopenharmony_ci#include <sys/wait.h> 15c0abf9e6Sopenharmony_ci#include <sys/stat.h> 16c0abf9e6Sopenharmony_ci#include <sys/types.h> 17c0abf9e6Sopenharmony_ci#include <libevdev/libevdev.h> 18c0abf9e6Sopenharmony_ci 19c0abf9e6Sopenharmony_ci#include "test-common.h" 20c0abf9e6Sopenharmony_ci 21c0abf9e6Sopenharmony_cistatic int 22c0abf9e6Sopenharmony_ciis_debugger_attached(void) 23c0abf9e6Sopenharmony_ci{ 24c0abf9e6Sopenharmony_ci int rc = 1; 25c0abf9e6Sopenharmony_ci /* 26c0abf9e6Sopenharmony_ci * FreeBSD does not support PTRACE_ATTACH, disable attaching a debugger 27c0abf9e6Sopenharmony_ci * on FreeBSD by skipping the rest of the function and just return 1. 28c0abf9e6Sopenharmony_ci */ 29c0abf9e6Sopenharmony_ci#ifndef __FreeBSD__ 30c0abf9e6Sopenharmony_ci int status; 31c0abf9e6Sopenharmony_ci int pid = fork(); 32c0abf9e6Sopenharmony_ci 33c0abf9e6Sopenharmony_ci if (pid == -1) 34c0abf9e6Sopenharmony_ci return 0; 35c0abf9e6Sopenharmony_ci 36c0abf9e6Sopenharmony_ci if (pid == 0) { 37c0abf9e6Sopenharmony_ci int ppid = getppid(); 38c0abf9e6Sopenharmony_ci if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) { 39c0abf9e6Sopenharmony_ci waitpid(ppid, NULL, 0); 40c0abf9e6Sopenharmony_ci ptrace(PTRACE_CONT, NULL, NULL); 41c0abf9e6Sopenharmony_ci ptrace(PTRACE_DETACH, ppid, NULL, NULL); 42c0abf9e6Sopenharmony_ci rc = 0; 43c0abf9e6Sopenharmony_ci } 44c0abf9e6Sopenharmony_ci _exit(rc); 45c0abf9e6Sopenharmony_ci } else { 46c0abf9e6Sopenharmony_ci waitpid(pid, &status, 0); 47c0abf9e6Sopenharmony_ci rc = WEXITSTATUS(status); 48c0abf9e6Sopenharmony_ci } 49c0abf9e6Sopenharmony_ci 50c0abf9e6Sopenharmony_ci#endif /* !__FreeBSD__ */ 51c0abf9e6Sopenharmony_ci return rc; 52c0abf9e6Sopenharmony_ci} 53c0abf9e6Sopenharmony_ci 54c0abf9e6Sopenharmony_cistatic bool 55c0abf9e6Sopenharmony_cidevice_nodes_exist(void) 56c0abf9e6Sopenharmony_ci{ 57c0abf9e6Sopenharmony_ci struct stat st; 58c0abf9e6Sopenharmony_ci int rc; 59c0abf9e6Sopenharmony_ci 60c0abf9e6Sopenharmony_ci rc = stat("/dev/uinput", &st); 61c0abf9e6Sopenharmony_ci if (rc == -1 && errno == ENOENT) 62c0abf9e6Sopenharmony_ci return false; 63c0abf9e6Sopenharmony_ci 64c0abf9e6Sopenharmony_ci rc = stat("/dev/input", &st); 65c0abf9e6Sopenharmony_ci if (rc == -1 && errno == ENOENT) 66c0abf9e6Sopenharmony_ci return false; 67c0abf9e6Sopenharmony_ci 68c0abf9e6Sopenharmony_ci /* Any issues but ENOENT we just let the test suite blow up later */ 69c0abf9e6Sopenharmony_ci return true; 70c0abf9e6Sopenharmony_ci} 71c0abf9e6Sopenharmony_ci 72c0abf9e6Sopenharmony_ciextern const struct libevdev_test __start_test_section, __stop_test_section; 73c0abf9e6Sopenharmony_ci 74c0abf9e6Sopenharmony_ciint main(void) 75c0abf9e6Sopenharmony_ci{ 76c0abf9e6Sopenharmony_ci const struct libevdev_test *t; 77c0abf9e6Sopenharmony_ci const struct rlimit corelimit = {0, 0}; 78c0abf9e6Sopenharmony_ci int failed; 79c0abf9e6Sopenharmony_ci 80c0abf9e6Sopenharmony_ci for (t = &__start_test_section; t < &__stop_test_section; t++) { 81c0abf9e6Sopenharmony_ci if (t->needs_root_privileges) { 82c0abf9e6Sopenharmony_ci if (getenv("LIBEVDEV_SKIP_ROOT_TESTS")) 83c0abf9e6Sopenharmony_ci return 77; 84c0abf9e6Sopenharmony_ci 85c0abf9e6Sopenharmony_ci if (getuid() != 0) { 86c0abf9e6Sopenharmony_ci fprintf(stderr, "This test needs to run as root\n"); 87c0abf9e6Sopenharmony_ci return 77; 88c0abf9e6Sopenharmony_ci } 89c0abf9e6Sopenharmony_ci if (!device_nodes_exist()) { 90c0abf9e6Sopenharmony_ci fprintf(stderr, "This test needs /dev/input and /dev/uinput to exist\n"); 91c0abf9e6Sopenharmony_ci return 77; 92c0abf9e6Sopenharmony_ci } 93c0abf9e6Sopenharmony_ci 94c0abf9e6Sopenharmony_ci break; 95c0abf9e6Sopenharmony_ci } 96c0abf9e6Sopenharmony_ci } 97c0abf9e6Sopenharmony_ci 98c0abf9e6Sopenharmony_ci if (is_debugger_attached()) 99c0abf9e6Sopenharmony_ci setenv("CK_FORK", "no", 0); 100c0abf9e6Sopenharmony_ci 101c0abf9e6Sopenharmony_ci if (setrlimit(RLIMIT_CORE, &corelimit) != 0) 102c0abf9e6Sopenharmony_ci perror("WARNING: Core dumps not disabled. Reason"); 103c0abf9e6Sopenharmony_ci 104c0abf9e6Sopenharmony_ci libevdev_set_log_function(test_logfunc_abort_on_error, NULL); 105c0abf9e6Sopenharmony_ci 106c0abf9e6Sopenharmony_ci SRunner *sr = srunner_create(NULL); 107c0abf9e6Sopenharmony_ci for (t = &__start_test_section; t < &__stop_test_section; t++) { 108c0abf9e6Sopenharmony_ci srunner_add_suite(sr, t->setup()); 109c0abf9e6Sopenharmony_ci } 110c0abf9e6Sopenharmony_ci 111c0abf9e6Sopenharmony_ci srunner_run_all(sr, CK_NORMAL); 112c0abf9e6Sopenharmony_ci 113c0abf9e6Sopenharmony_ci failed = srunner_ntests_failed(sr); 114c0abf9e6Sopenharmony_ci srunner_free(sr); 115c0abf9e6Sopenharmony_ci 116c0abf9e6Sopenharmony_ci return failed; 117c0abf9e6Sopenharmony_ci} 118