Files
palera1n/src/main.c
T
e332a00cf9 merge tui! (#409)
* Merge main into tui (#406)

* plooshInit support

* Add override libcheckra1nhelper option

* update credits.c

* Update build.yml

---------

Co-authored-by: Nick Chan <[email protected]>
Co-authored-by: meow <[email protected]>

* Add TUI

* ISO C forbids an empty translation unit

* Default to TUI

* thanks iPadOS

* I forgot

* make random quotes more related (#408)

Definitely a good concept of the TUI (and one that I am a fan of), but (as has been somewhat brought up by others) we should probably make them more related to checkm8, checkra1n, or palera1n (since those are the types of things that this tool is based off of)

* "Connect your iPhone, iPad, iPod Touch, or Apple TV"

* Add Linux TTY support

* DIsable TUI for certain options

* Fix boot-args overflow

* auto reposition cursor

* Moved droplet, no one could behave

* Move the droplet back because it actually made it worse

---------

Co-authored-by: Nick Chan <[email protected]>
Co-authored-by: meow <[email protected]>
Co-authored-by: Michael <[email protected]>
Co-authored-by: Samara <[email protected]>
2024-03-27 22:50:45 -07:00

189 lines
5.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <assert.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pthread.h>
#include <inttypes.h>
#include <errno.h>
#include <spawn.h>
#include <sys/mman.h>
#include <time.h>
#include <libimobiledevice/libimobiledevice.h>
#include <ANSI-color-codes.h>
#include <palerain.h>
#include <xxd-embedded.h>
#include <paleinfo.h>
#define CMD_LEN_MAX 512
#define OVERRIDE_MAGIC 0xd803b376
unsigned int verbose = 0;
/* we want to write to them so don't use string literals */
char xargs_cmd[0x270] = { 'x', 'a', 'r', 'g', 's', '\0' },
palerain_flags_cmd[0x30] = { 'd', 'e', 'a', 'd', 'b', 'e', 'e', 'f', '\0' };
extern char** environ;
niarelap_file_t* kpf_to_upload_1 = &checkra1n_kpf_pongo_lzma;
niarelap_file_t* ramdisk_to_upload_1 = &ramdisk_dmg_lzma;
niarelap_file_t* overlay_to_upload_1 = &binpack_dmg;
niarelap_file_t** kpf_to_upload = &kpf_to_upload_1;
niarelap_file_t** ramdisk_to_upload = &ramdisk_to_upload_1;
niarelap_file_t** overlay_to_upload = &overlay_to_upload_1;
override_file_t override_ramdisk, override_kpf, override_overlay;
uint64_t palerain_flags = 0;
pthread_mutex_t log_mutex;
pthread_t dfuhelper_thread, pongo_thread;
void thr_cleanup(void* ptr) {
*(int*)ptr = 0;
}
int build_checks(void) {
#ifndef NO_CHECKRAIN
#if defined(__APPLE__)
struct mach_header_64* c1_header = (struct mach_header_64*)&checkra1n[0];
if (c1_header->magic != MH_MAGIC_64 && c1_header->magic != MH_CIGAM_64) {
LOG(LOG_FATAL, "Broken build: checkra1n is not a thin Mach-O");
return -1;
}
if (c1_header->cputype != _mh_execute_header.cputype) {
LOG(LOG_FATAL, "Broken build: checkra1n CPU type does not match palera1n CPU type");
return -1;
}
#endif
if (checkra1n_len <= (UCHAR_MAX + 1)) {
LOG(LOG_FATAL, "checkra1n too small");
}
if (boyermoore_horspool_memmem(&checkra1n[0], checkra1n_len, (const unsigned char *)"[ra1npoc15-part] thanks to", strlen("[ra1npoc15-part] thanks to")) != NULL) {
palerain_flags |= palerain_option_checkrain_is_clone;
}
#endif
return 0;
}
#ifdef TUI
bool tui_started = false;
#endif
#ifdef USE_LIBUSB
void log_cb(libusb_context *ctx, enum libusb_log_level level, const char *str) {
LOG(level + 0, str);
}
#endif
// save argc, argv, and envp for restarting
int saved_argc;
char** saved_argv;
char** saved_envp;
int palera1n(int argc, char *argv[], char *envp[]) {
saved_argc = argc;
saved_argv = argv;
saved_envp = envp;
print_credits();
int ret = 0;
pthread_mutex_init(&log_mutex, NULL);
pthread_mutex_init(&spin_mutex, NULL);
pthread_mutex_init(&found_pongo_mutex, NULL);
pthread_mutex_init(&ecid_dfu_wait_mutex, NULL);
if ((ret = build_checks())) return ret;
if ((ret = optparse(argc, argv))) goto cleanup;
if (!(palerain_flags & palerain_option_device_info) && (palerain_flags & palerain_option_palerain_version)) goto normal_exit;
#ifdef TUI
if ((palerain_flags & palerain_option_tui) || (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && !(palerain_flags & palerain_option_cli))) {
ret = tui();
if (ret) goto cleanup;
else goto normal_exit;
}
#endif
#ifdef USE_LIBUSB
{
libusb_set_log_cb(NULL, log_cb, LIBUSB_LOG_CB_GLOBAL);
libusb_context* ctx = NULL;
int test_libusb = libusb_init(&ctx);
if (test_libusb) {
LOG(LOG_ERROR, "cannot initialize libusb: %d (%s)\n", test_libusb, libusb_strerror(test_libusb));
libusb_exit(ctx);
goto cleanup;
}
libusb_exit(ctx);
}
#endif
if (!(palerain_flags & palerain_option_device_info))
LOG(LOG_INFO, "Waiting for devices");
if (getenv("USBMUXD_SOCKET_ADDRESS") == NULL && access("/var/run/usbmuxd", F_OK) != 0)
LOG(LOG_WARNING, "/var/run/usbmuxd not found, normal mode device detection will not work.");
pthread_create(&pongo_thread, NULL, pongo_helper, NULL);
pthread_create(&dfuhelper_thread, NULL, dfuhelper, NULL);
pthread_join(dfuhelper_thread, NULL);
set_spin(0);
if ((palerain_flags & (palerain_option_dfuhelper_only |
palerain_option_reboot_device |
palerain_option_exit_recovery |
palerain_option_enter_recovery |
palerain_option_device_info)
) || device_has_booted)
goto normal_exit;
if (exec_checkra1n()) goto cleanup;
if ((palerain_flags & (palerain_option_pongo_exit | palerain_option_demote)))
goto normal_exit;
set_spin(1);
sleep(2);
pthread_create(&pongo_thread, NULL, pongo_helper, NULL);
pthread_join(pongo_thread, NULL);
while (get_spin())
{
sleep(1);
}
normal_exit:
cleanup:
if (override_kpf.magic == OVERRIDE_MAGIC) {
munmap(override_kpf.ptr, (size_t)override_kpf.len);
close(override_kpf.fd);
}
if (override_ramdisk.magic == OVERRIDE_MAGIC) {
munmap(override_ramdisk.ptr, (size_t)override_ramdisk.len);
close(override_ramdisk.fd);
}
if (override_overlay.magic == OVERRIDE_MAGIC) {
munmap(override_overlay.ptr, (size_t)override_overlay.len);
close(override_overlay.fd);
}
if (ext_checkra1n != NULL) free(ext_checkra1n);
pthread_mutex_destroy(&log_mutex);
pthread_mutex_destroy(&spin_mutex);
pthread_mutex_destroy(&found_pongo_mutex);
pthread_mutex_destroy(&ecid_dfu_wait_mutex);
return ret;
}
int main (int argc, char* argv[], char* envp[]) {
return palera1n(argc, argv, envp);
}