diff --git a/.builds/freebsd-x64.yml.disabled b/.builds/freebsd-x64.yml similarity index 56% rename from .builds/freebsd-x64.yml.disabled rename to .builds/freebsd-x64.yml index 55c9496a..41cc26c4 100644 --- a/.builds/freebsd-x64.yml.disabled +++ b/.builds/freebsd-x64.yml @@ -1,5 +1,7 @@ image: freebsd/latest packages: + - evdev-proto + - libepoll-shim - meson - ninja - pkgconf @@ -11,10 +13,9 @@ packages: - harfbuzz - pixman - libxkbcommon - - ncurses - check - - ttf-hack - - font-noto-emoji + - hack-font + - noto-emoji sources: - https://codeberg.org/dnkl/foot @@ -24,14 +25,16 @@ sources: # condition: failure # to: +# TODO: drop -Dc_args=-Wno-missing-braces when freebsd/latest is >= 13 + tasks: - debug: | mkdir -p bld/debug - meson --buildtype=debug -Dfcft:text-shaping=enabled -Dfcft:test-text-shaping=true foot bld/debug + meson --buildtype=debug -Dc_args=-Wno-missing-braces -Dterminfo=false -Dfcft:text-shaping=enabled -Dfcft:test-text-shaping=true foot bld/debug ninja -C bld/debug -k0 meson test -C bld/debug --print-errorlogs - release: | mkdir -p bld/release - meson --buildtype=minsize -Dfcft:text-shaping=enabled -Dfcft:test-text-shaping=true foot bld/release + meson --buildtype=minsize -Dc_args=-Wno-missing-braces -Dterminfo=false -Dfcft:text-shaping=enabled -Dfcft:test-text-shaping=true foot bld/release ninja -C bld/release -k0 meson test -C bld/release --print-errorlogs diff --git a/CHANGELOG.md b/CHANGELOG.md index 767f5669..c43c8f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ * Key/mouse binding `select-extend-character-wise`, which forces the selection mode to 'character-wise' when extending a selection. * `DECSET` `47`, `1047` and `1048`. +* FreeBSD support ### Changed @@ -91,6 +92,7 @@ * [birger](https://codeberg.org/birger) * [pc](https://codeberg.org/pc) * [FollieHiyuki](https://codeberg.org/FollieHiyuki) +* jbeich ## 1.6.2 diff --git a/client.c b/client.c index 80eb8b40..dead7117 100644 --- a/client.c +++ b/client.c @@ -9,7 +9,7 @@ #include #include -#include +#include #define LOG_MODULE "foot-client" #define LOG_ENABLE_DBG 0 @@ -263,7 +263,7 @@ main(int argc, char *const *argv) }; /* Total packet length, not (yet) including argv[] */ - size_t total_len = ( + uint64_t total_len = ( sizeof(data) + cwd_len + term_len + diff --git a/completions/zsh/_foot b/completions/zsh/_foot index 24ddd671..c6f0f93b 100644 --- a/completions/zsh/_foot +++ b/completions/zsh/_foot @@ -31,6 +31,6 @@ case ${state} in ;; terms) - _values 'terminal definitions' $(find /usr/share/terminfo -type f -printf "%f\n") + _values 'terminal definitions' /usr/share/terminfo/**/*(.:t) ;; esac diff --git a/completions/zsh/_footclient b/completions/zsh/_footclient index 26aa2c5c..e355527f 100644 --- a/completions/zsh/_footclient +++ b/completions/zsh/_footclient @@ -20,6 +20,6 @@ _arguments \ case ${state} in terms) - _values 'terminal definitions' $(find /usr/share/terminfo -type f -printf "%f\n") + _values 'terminal definitions' /usr/share/terminfo/**/*(.:t) ;; esac diff --git a/config.c b/config.c index 5956a516..da55f8f8 100644 --- a/config.c +++ b/config.c @@ -2042,7 +2042,11 @@ config_load(struct config *conf, const char *conf_path, bool ret = false; *conf = (struct config) { +#ifdef HAVE_TERMINFO .term = xstrdup("foot"), +#else + .term = xstrdup("xterm-256color"), +#endif .shell = get_shell(), .title = xstrdup("foot"), .app_id = xstrdup("foot"), diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 16fd270b..c78ad7bc 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -29,7 +29,8 @@ in this order: by prepending a '-' to argv[0]. Default: _no_. *term* - Value to set the environment variable *TERM* to. Default: _foot_. + Value to set the environment variable *TERM* to. Default: _foot_ + or _xterm-256color_ if built with _-Dterminfo=false_ *font*, *font-bold*, *font-italic*, *font-bold-italic* Comma separated list of fonts to use, in fontconfig format. That diff --git a/foot.ini b/foot.ini index 3cff1842..330b4b7f 100644 --- a/foot.ini +++ b/foot.ini @@ -1,7 +1,7 @@ # -*- conf -*- # shell=$SHELL (if set, otherwise user's default shell from /etc/passwd) -# term=foot +# term=foot (or xterm-256color if built with -Dterminfo=false) # login-shell=no # font=monospace:size=8 diff --git a/main.c b/main.c index 2775a50d..c0dad5e3 100644 --- a/main.c +++ b/main.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff --git a/meson.build b/meson.build index f943211c..f747957f 100644 --- a/meson.build +++ b/meson.build @@ -12,8 +12,12 @@ is_debug_build = get_option('buildtype').startswith('debug') cc = meson.get_compiler('c') +if cc.has_function('memfd_create') + add_project_arguments('-DMEMFD_CREATE', language: 'c') +endif + add_project_arguments( - ['-D_POSIX_C_SOURCE=200809L', '-D_GNU_SOURCE=200809L'] + + ['-D_GNU_SOURCE=200809L'] + (is_debug_build ? ['-D_DEBUG'] : [cc.get_supported_arguments('-fno-asynchronous-unwind-tables')]) + @@ -56,7 +60,8 @@ if cc.has_argument('-fmacro-prefix-map=/foo=') endif math = cc.find_library('m') -threads = dependency('threads') +threads = [dependency('threads'), cc.find_library('stdthreads', required: false)] +libepoll = dependency('epoll-shim', required: false) pixman = dependency('pixman-1') wayland_protocols = dependency('wayland-protocols') wayland_client = dependency('wayland-client') @@ -67,6 +72,11 @@ fontconfig = dependency('fontconfig') tllist = dependency('tllist', version: '>=1.0.4', fallback: 'tllist') fcft = dependency('fcft', version: ['>=2.3.0', '<3.0.0'], fallback: 'fcft') +tic = find_program('tic', native: true, required: get_option('terminfo')) +if tic.found() + add_project_arguments('-DHAVE_TERMINFO', language: 'c') +endif + wayland_protocols_datadir = wayland_protocols.get_pkgconfig_variable('pkgdatadir') wscanner = dependency('wayland-scanner', native: true) @@ -126,7 +136,7 @@ vtlib = static_library( 'vt.c', 'vt.h', wl_proto_src + wl_proto_headers, version, - dependencies: [pixman, fcft, tllist], + dependencies: [libepoll, pixman, fcft, tllist, wayland_client], link_with: misc, ) @@ -136,7 +146,7 @@ pgolib = static_library( 'selection.c', 'selection.h', 'terminal.c', 'terminal.h', wl_proto_src + wl_proto_headers, - dependencies: [pixman, fcft, tllist], + dependencies: [libepoll, pixman, fcft, tllist, wayland_client], link_with: vtlib, ) @@ -144,7 +154,7 @@ executable( 'pgo', 'pgo/pgo.c', wl_proto_src + wl_proto_headers, - dependencies: [math, threads, pixman, wayland_client, fcft, tllist], + dependencies: [math, threads, libepoll, pixman, wayland_client, fcft, tllist], link_with: pgolib, ) @@ -173,7 +183,7 @@ executable( 'user-notification.h', 'wayland.c', 'wayland.h', wl_proto_src + wl_proto_headers, version, - dependencies: [math, threads, pixman, wayland_client, wayland_cursor, xkb, fontconfig, + dependencies: [math, threads, libepoll, pixman, wayland_client, wayland_cursor, xkb, fontconfig, tllist, fcft], link_with: pgolib, install: true) @@ -189,14 +199,15 @@ executable( version, install: true) -tic = find_program('tic', native: true) -custom_target( - 'terminfo', - output: 'f', - input: 'foot.info', - command: [tic, '-x', '-o', '@OUTDIR@', '-e', 'foot,foot-direct', '@INPUT@'], - install: true, - install_dir: join_paths(get_option('datadir'), 'terminfo')) +if tic.found() + custom_target( + 'terminfo', + output: 'f', + input: 'foot.info', + command: [tic, '-x', '-o', '@OUTDIR@', '-e', 'foot,foot-direct', '@INPUT@'], + install: true, + install_dir: join_paths(get_option('datadir'), 'terminfo')) +endif install_data( 'LICENSE', 'README.md', 'CHANGELOG.md', diff --git a/meson_options.txt b/meson_options.txt index fc3c1b0f..0a5b0a3d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1 +1,2 @@ option('ime', type: 'boolean', value: true, description: 'IME (Input Method Editor) support') +option('terminfo', type: 'boolean', value: true, description: 'Install terminfo') diff --git a/pgo/pgo.c b/pgo/pgo.c index 39c20de0..fa95a0ec 100644 --- a/pgo/pgo.c +++ b/pgo/pgo.c @@ -257,7 +257,16 @@ main(int argc, const char *const *argv) close(fd); +#if defined(MEMFD_CREATE) int mem_fd = memfd_create("foot-pgo-ptmx", MFD_CLOEXEC); +#elif defined(__FreeBSD__) + // memfd_create on FreeBSD 13 is SHM_ANON without sealing support + int mem_fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600); +#else + char name[] = "/tmp/foot-pgo-ptmx-XXXXXX"; + int mem_fd = mkostemp(name, O_CLOEXEC); + unlink(name); +#endif if (mem_fd < 0) { fprintf(stderr, "error: failed to create memory FD\n"); goto out; diff --git a/render.c b/render.c index f8bb4968..2dccd6a8 100644 --- a/render.c +++ b/render.c @@ -5,7 +5,13 @@ #include #include #include -#include +#include +#if __has_include() +#include +#define pthread_setname_np(thread, name) (pthread_set_name_np(thread, name), 0) +#elif defined(__NetBSD__) +#define pthread_setname_np(thread, name) pthread_setname_np(thread, "%s", (void *)name) +#endif #include #include @@ -1231,7 +1237,7 @@ render_worker_thread(void *_ctx) char proc_title[16]; snprintf(proc_title, sizeof(proc_title), "foot:render:%d", my_id); - if (prctl(PR_SET_NAME, proc_title, 0, 0, 0) < 0) + if (pthread_setname_np(pthread_self(), proc_title) < 0) LOG_ERRNO("render worker %d: failed to set process title", my_id); sem_t *start = &term->render.workers.start; diff --git a/server.c b/server.c index c5db036d..7a4101ea 100644 --- a/server.c +++ b/server.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include diff --git a/shm.c b/shm.c index 2231f057..2ec581c4 100644 --- a/shm.c +++ b/shm.c @@ -9,8 +9,7 @@ #include #include #include -#include -#include +#include #include #include @@ -130,6 +129,7 @@ static const struct wl_buffer_listener buffer_listener = { .release = &buffer_release, }; +#if __SIZEOF_POINTER__ == 8 static size_t page_size(void) { @@ -146,6 +146,7 @@ page_size(void) xassert(size > 0); return size; } +#endif static bool instantiate_offset(struct wl_shm *shm, struct buffer *buf, off_t new_offset) @@ -274,18 +275,27 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie, LOG_DBG("cookie=%lx: allocating new buffer: %zu KB", cookie, size / 1024); /* Backing memory for SHM */ +#if defined(MEMFD_CREATE) pool_fd = memfd_create("foot-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING); +#elif defined(__FreeBSD__) + // memfd_create on FreeBSD 13 is SHM_ANON without sealing support + pool_fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600); +#else + char name[] = "/tmp/foot-wayland-shm-buffer-pool-XXXXXX"; + pool_fd = mkostemp(name, O_CLOEXEC); + unlink(name); +#endif if (pool_fd == -1) { LOG_ERRNO("failed to create SHM backing memory file"); goto err; } -#if defined(__i386__) - off_t initial_offset = 0; - off_t memfd_size = size; -#else +#if __SIZEOF_POINTER__ == 8 off_t initial_offset = scrollable && max_pool_size > 0 ? (max_pool_size / 4) & ~(page_size() - 1) : 0; off_t memfd_size = scrollable && max_pool_size > 0 ? max_pool_size : size; +#else + off_t initial_offset = 0; + off_t memfd_size = size; #endif LOG_DBG("memfd-size: %lu, initial offset: %lu", memfd_size, initial_offset); @@ -297,7 +307,7 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie, if (!can_punch_hole_initialized) { can_punch_hole_initialized = true; -#if defined(__x86_64__) +#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE) can_punch_hole = fallocate( pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0; @@ -333,6 +343,7 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie, goto err; } +#if defined(MEMFD_CREATE) /* Seal file - we no longer allow any kind of resizing */ /* TODO: wayland mmaps(PROT_WRITE), for some unknown reason, hence we cannot use F_SEAL_FUTURE_WRITE */ if (fcntl(pool_fd, F_ADD_SEALS, @@ -341,6 +352,7 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie, LOG_ERRNO("failed to seal SHM backing memory file"); /* This is not a fatal error */ } +#endif pool = wl_shm_create_pool(shm, pool_fd, memfd_size); if (pool == NULL) { @@ -400,14 +412,15 @@ err: bool shm_can_scroll(const struct buffer *buf) { -#if defined(__i386__) +#if __SIZEOF_POINTER__ == 8 + return can_punch_hole && max_pool_size > 0 && buf->scrollable; +#else /* Not enough virtual address space in 32-bit */ return false; -#else - return can_punch_hole && max_pool_size > 0 && buf->scrollable; #endif } +#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE) static bool wrap_buffer(struct wl_shm *shm, struct buffer *buf, off_t new_offset) { @@ -640,12 +653,14 @@ err: abort(); return false; } +#endif /* FALLOC_FL_PUNCH_HOLE */ bool shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows, int top_margin, int top_keep_rows, int bottom_margin, int bottom_keep_rows) { +#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE) if (!shm_can_scroll(buf)) return false; @@ -653,6 +668,9 @@ shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows, return rows > 0 ? shm_scroll_forward(shm, buf, rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows) : shm_scroll_reverse(shm, buf, -rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows); +#else + return false; +#endif } void diff --git a/slave.c b/slave.c index 79008e5d..29ad92f5 100644 --- a/slave.c +++ b/slave.c @@ -178,6 +178,7 @@ slave_exec(int ptmx, char *argv[], int err_fd, bool login_shell, goto err; } +#ifdef IUTF8 { struct termios flags; if (tcgetattr(pts, &flags) < 0) { @@ -191,6 +192,7 @@ slave_exec(int ptmx, char *argv[], int err_fd, bool login_shell, goto err; } } +#endif if (tll_length(*notifications) > 0) { int flags = fcntl(pts, F_GETFL); diff --git a/terminal.c b/terminal.c index 312da6dd..bb62195d 100644 --- a/terminal.c +++ b/terminal.c @@ -1,6 +1,9 @@ #include "terminal.h" +#if defined(__GLIBC__) #include +#endif +#include #include #include #include diff --git a/uri.c b/uri.c index 21eba6fb..51cd8093 100644 --- a/uri.c +++ b/uri.c @@ -266,7 +266,7 @@ err: bool hostname_is_localhost(const char *hostname) { - char this_host[HOST_NAME_MAX]; + char this_host[_POSIX_HOST_NAME_MAX]; if (gethostname(this_host, sizeof(this_host)) < 0) this_host[0] = '\0';