Commit graph

60 commits

Author SHA1 Message Date
Daniel Eklöf
b3d0cdd4b2
slave: roll our own ‘execvpe()’ on FreeBSD 2022-04-12 15:07:41 +02:00
Daniel Eklöf
fd414f79be
client/slave: explictly add ‘extern char **environ’
It’s not in any header files on FreeBSD.
2022-04-12 15:07:41 +02:00
Daniel Eklöf
d02124902b
client: add -E,--client-environment
When this option is used, the child process in the new terminal
instance will inherit its environment from the footclient process,
instead of the foot server’s.

Implemented by sending (yet another) dynamic string list as part of
the client -> server setup packet. When the new option is *not* used,
the setup packet is now 2 bytes larger than before.

On the server side, the slave process now uses execvpe() instead of
execvp(). There’s plumbing to propagate a new ‘envp’ argument from
term_init() all the way down to slave_exec(). If ‘envp’ is NULL, we
use ‘environ’ instead (thus matching the old behavior of execvp()).

Closes #1004
2022-04-12 15:07:40 +02:00
Craig Barnes
23cf80667a Explicitly initialize sigaction::sa_mask members with sigemptyset(3)
Not doing so before calling sigaction(3) is "undefined" according to
POSIX[1]:

> Applications shall call either sigemptyset() or sigfillset() at least
> once for each object of type sigset_t prior to any other use of that
> object. If such an object is not initialized in this way, but is
> nonetheless supplied as an argument to any of pthread_sigmask(),
> sigaction(), sigaddset(), sigdelset(), sigismember(), sigpending(),
> sigprocmask(), sigsuspend(), sigtimedwait(), sigwait(), or
> sigwaitinfo(), the results are undefined.

The use of designated initializers means that sa_mask members were
still being initialized, but sigset_t is an opaque type and implicit
initialization doesn't necessarily produce the same results as using
sigemptyset(3) (although it typically does on most implementations).

[1]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaddset.html
2022-02-12 12:26:42 +00:00
Daniel Eklöf
027603cbb8
slave: re-use ‘struct sigaction’ variable when resetting SIGHUP+SIGPIPE 2021-12-18 23:22:52 +01:00
Daniel Eklöf
fb488b6162
slave: restore SIGPIPE 2021-12-18 23:20:10 +01:00
Daniel Eklöf
064121ee95
slave: log _which_ CWD we failed to change to 2021-08-30 17:55:16 +02:00
Daniel Eklöf
8a7264e905
slave: set TERMINFO instead of TERMINFO_DIRS
This seems to be slightly better supported than TERMINFO_DIRS. It also
simplifies our code, since it’s no longer an issue of whether to
append or not - we just set TERMINFO, and ignore whatever it was set
to before.

Also closes #687
2021-08-18 20:18:35 +02:00
Daniel Eklöf
7639186865
terminfo: install to $datadir/foot/terminfo by default, append to TERMINFO_DIRS
As of 2021-07-31, ncurses ships its own version of foot’s terminfo.

Since:

* It doesn’t have the non-standard Sync,Tc,setrgbf,setrgbb
  capabilities.
* It doesn’t set hs,fsl,dsl (statusbar).
* We want to be able to update our termminfo without waiting for an
  ncurses release.
* Foot should be installable and usable on Linux systems that doesn’t
  have the latest ncurses.

we still want to ship our own version. We can however not install it
to the default terminfo location (e.g. /usr/share/terminfo), since it
will collide with the ncurses provided files.

Our options are to either rename our terminfo to something else, or to
keep the name, but install our terminfo files somewhere else.

The first option would be the easy one. However, I think it makes
sense to use the same name. For example, a user that SSH’s into a
remote system that does *not* have our own version installed,
but *does* have the ncurses one, will gracefully fall back to that
one, which is better than manually having to set
e.g. TERM=xterm-256color.

Now, if we want to use the same name, we need to install it somewhere
else. But where? And how do we ensure our version is preferred over
the ncurses one?

I opted to $datadir/foot/terminfo (e.g. /usr/share/foot/terminfo) by
default. It makes it namespaced to foot (i.e. we’re not introducing a
new “standard” terminfo location), thus guaranteeing it wont collide
with ncurses.

To enable applications to find it, we export TERMINFO_DIRS. This is a
list of *additional* directories to search for terminfo files. If it’s
already defined, we *append* to it.

The nice thing with this is, if there’s no terminfo in that
location (e.g. when you SSH into a remote), the default terminfo
location is *also* searched. But only *after* having searched through
TERMINFO_DIRS.

In short: our version is preferred, but the ncurses one (or an older
version of our terminfo package!) will be used if ours cannot be
found.

To enable packagers full control over the new behavior, the existing
meson command line options have been modified, and a new option added:

-Dterminfo=disabled|enabled|auto: *build* and *install* the terminfo
files.

-Dcustom-terminfo-install-location=<path>: *where* the terminfo files
are expected to be found.

This *needs* to be set *even* if -Dterminfo=disabled. For example, if
the packaging script builds and packages the terminfo files separate
from the regular foot build. The path is *relative to $prefix*, and
defaults to $datadir/foot/terminfo.

This is the value that will be appended to TERMINFO_DIRS. Note that
you can set it to ‘no’, in which case foot will *not* set/modify
TERMINFO_DIRS. Only do this if you don’t intend to package foot’s
terminfo files at all (i.e. you plan on using the ncurses ones only).

-Ddefault-terminfo=foot. Allows overriding the default TERM
value. This should only be changed if the target platform doesn’t
support terminfo files.

Closes #671
2021-08-17 21:04:30 +02:00
Daniel Eklöf
42ec264075
tokenize: strdup() each individual argv
Instead of referencing the un-tokenized “raw” command string, strdup()
each argv. This way, the input string can be ‘const’.
2021-06-20 14:19:22 +02:00
Daniel Eklöf
a72b2688bd
slave/spawn: restore SIGHUP handler after fork(), before exec()
Foot installs a SIG_IGN handler for SIGHUP. Ignored signals are
inherited in sub-processes. Thus, we need to restore it to SIG_DFL
before exec:ing.
2021-06-02 20:13:14 +02:00
Daniel Eklöf
b75bd6507a
notifications: use \e[22m to disable bold
\e[21m was previously used to disable bold. That changed a while ago,
to align foot with the majority of other terminal emulators.

\e[22m now disables both bold and dim.

When this change was done, the user notifications were not updated,
meaning the ‘message’ part was always in bold. This was never the
intended behavior.
2021-05-20 17:51:04 +02:00
Daniel Eklöf
555f751f94
errno: don’t use ‘_errno’ as a variable name; _ are reserved for use as identifiers 2021-02-21 20:33:07 +01:00
Daniel Eklöf
dd5c31657e
spawn/slave: restore signal mask after fork
slave: no need to restore signal handlers; they are automatically
restored as long as they are not SIG_IGN (which they never are in
foot).

spawn(): restore signal mask after fork. This fixes an issue where a
terminal spawned with ctrl+shift+n did not terminate when its shell
exited.

Closes #366
2021-02-21 19:59:50 +01:00
Craig Barnes
19a5f25b80 Mark slave_exec() as "noreturn" and convert xassert(false) to BUG(...) 2021-02-10 09:18:50 +00:00
Jan Beich
67e713ff3a
slave: skip e310487dae if not supported
slave.c:188:26: error: use of undeclared identifier 'IUTF8'
        flags.c_iflag |= IUTF8;
                         ^
2021-01-21 12:00:02 +01:00
Craig Barnes
e56136ce11 debug: rename assert() to xassert(), to avoid clashing with <assert.h> 2021-01-16 20:16:00 +00:00
Craig Barnes
22f25a9e4f Print stack trace on assert() failure or when calling fatal_error()
Note: this uses the __sanitizer_print_stack_trace() function from the
AddressSanitizer runtime, so it only works when AddressSanitizer is
in use.
2021-01-16 19:56:33 +00:00
Daniel Eklöf
c779a5ec7d
log: include 'fmt' in __VA_ARGS__
This ensures all calls have at least one __VA_ARGS__ argument, thus
making them ISO C99 compliant.
2020-08-23 10:07:08 +02:00
Craig Barnes
26fccae03d slave: set $COLORTERM environment variable to "truecolor"
This is also done by libvte, alacritty, kitty and several other
terminal emulators as a way to indicate support for 24-bit RGB
colors. It generally also implies support for the xterm 256-color
palette and basic ECMA-48 colors.
2020-08-23 05:33:48 +01:00
Craig Barnes
7a77958ba2 Convert most dynamic allocations to use functions from xmalloc.h 2020-08-08 20:37:57 +01:00
Craig Barnes
11a1d99da7 Replace non-portable "\e" escape in string literals with "\033" 2020-08-02 23:54:04 +01:00
Daniel Eklöf
bae3244ec6
Revert "slave: use an event FD to communicate errors after fork before exec"
This reverts commit 027a8de6f5.

I was a bit quick on this one, and only tested error cases. Turns out,
this causes foot to hang in a blocking read(3) on the event FD.

This is because while the FD has FD_CLOEXEC, that flag is per file
descriptor. I.e. the forked copy of the event fd is closed when we
exec(), but since this isn't a pipe, nothing is signaled to the parent
process, which thus remains blocking in read(3) since its copy of the
event fd hasn't been closed.

We _could_ write a dummy value on the event fd just before exec(), but
then we wouldn't be able to catch errors from exec() self - only
errors *before* exec().
2020-08-01 09:41:31 +02:00
Daniel Eklöf
027a8de6f5
slave: use an event FD to communicate errors after fork before exec
Replace the pipe we used to communicate errors after fork(), but
before exec() to the parent process with an event FD.

The overhead in the kernel is much lower to setup an event fd,
compared to a pipe.
2020-08-01 09:33:43 +02:00
Daniel Eklöf
c8e78674ed
slave: emit user-notifications before dup:ing stdin/stdout/stderr
Since we need to restore the status flags anyway, there's nothing to
gain from emitting the user notifications after dup:ing the pts file
descriptor.

On the other hand, emitting user notifications *before* dup:ing means
we can still print error messages for e.g. write(3) errors.
2020-08-01 09:00:18 +02:00
Daniel Eklöf
7e93405b1a
slave: user-notifications: skip the O_NONBLOCK dance when there aren't any notifications 2020-07-31 19:52:50 +02:00
Daniel Eklöf
1da8142f32
slave: restore pts file status flags after emitting user-notifications
We (need to) set O_NONBLOCK on the pts file description before
emitting the user-notifications, to ensure we don't block in write(3).

However, since file status flags are per *file*, not per
file *descriptor*, this ends up setting O_NONBLOCK on the dup:ed
stdin/stdout/stderr file descriptors too.

Not all clients want this, or can handle this.

Thus we need to restore the original flags before exec:ing the client.

This fixes "makepkg" build failures.
2020-07-31 18:13:00 +02:00
Daniel Eklöf
a7d21c5c7f
slave: user-notifications: don't block in write(3)
The main process is blocking and waiting for us to close the error
pipe (in exec(3), via O_CLOEXEC).

Thus, pts data will *not* be processed until we've exec:d the shell.

Because of this we must not write too much and block in write(3). Do
this by setting O_NONBLOCK on the pts fd (*after* dup:ing it to
stdin/stderr/sdout) and watch for EAGAIN EWOULDBLOCK.
2020-07-31 17:15:51 +02:00
Daniel Eklöf
b661513245
slave: user-notifications: emit errors first, then warnings and last deprecations 2020-07-31 17:10:39 +02:00
Daniel Eklöf
f6533a71e4
user-notification: 'productify' the user-warning system
* Rename user_warning to user_notification
* Add warning and error types (in addition to the existing deprecated)
* Simplify logic when emitting a user notification after forking; we
  don't need to copy the notification data since we're in a new
  process and have total control over that memory.
2020-07-30 18:58:54 +02:00
Daniel Eklöf
113759b0a9
slave: don't ignore write(3) errors 2020-07-29 19:46:20 +02:00
Daniel Eklöf
b3d0215c38
term: add capability to print warnings *inside* the terminal
This is intended to be used to print e.g. deprecation warnings inside
the terminal, *before* the shell is started.
2020-07-29 19:42:12 +02:00
Daniel Eklöf
e310487dae
slave: set IUTF8 2020-05-26 18:18:11 +02:00
Daniel Eklöf
c605503df6
slave: restore signal mask 2020-05-21 20:22:24 +02:00
Daniel Eklöf
e654cf3880
slave: configure pts to be the controlling terminal of the forked process 2020-05-13 13:07:44 +02:00
Daniel Eklöf
6912bbd310
slave: set $SHELL when command line is a shell listed in /etc/shells 2020-03-02 18:46:35 +01:00
Daniel Eklöf
f1b1ac39f6
slave: check return value of chdir() 2020-02-20 18:46:35 +01:00
Daniel Eklöf
b5efe984bb
slave: prefix argv[0] with a '-' when spawning a login-shell 2020-02-20 18:36:09 +01:00
Daniel Eklöf
39146fac5c
term: term_init: add 'cwd' argument
This is used when spawning the slave, to set its current working
directory just before we exec() the client.

In a regular foot instance, we set the cwd from getcwd().

In a foot server instance, each connecting client sends its cwd to the
server, and we use that.
2019-12-21 19:57:28 +01:00
Daniel Eklöf
57de9feaa5
term: term_spawn_new(): new function, spawns a new foot/footclient process
Bind ctrl+shift+return to it
2019-12-21 15:27:17 +01:00
Daniel Eklöf
61dfa1365e
slave: restore signals before calling exec() 2019-11-03 13:24:15 +01:00
Daniel Eklöf
d3e4ba6c94
slave: remove unneeded define 2019-11-03 13:02:16 +01:00
Daniel Eklöf
8cf981ca12
slave: turn on FD_CLOEXEC after slave has been spawned
This ensures that our ptmx FD isn't carried over to other terminals
spawned later.
2019-11-03 01:14:02 +01:00
Daniel Eklöf
69d62d3cd2
slave: set TERM environment variable in slave process 2019-11-01 21:01:15 +01:00
Daniel Eklöf
54039c1fb4
slave: log child's errno, not parents 2019-10-30 20:21:19 +01:00
Daniel Eklöf
98ccd01c1b
slave: fix debug logging (no 'term' variable) 2019-10-30 20:20:56 +01:00
Daniel Eklöf
18921f7f45
term: move client startup to a new function, slave_spawn() 2019-10-30 18:05:03 +01:00
Daniel Eklöf
ce5f5e4d51
slave: rename slave_spawn() -> slave_exec() 2019-10-30 17:30:58 +01:00
Daniel Eklöf
c11cc2be57
main: allow user to override shell on the command line 2019-07-17 09:55:36 +02:00
Daniel Eklöf
2046dc0fbd
slave: break out command line tokenizer 2019-07-17 09:46:45 +02:00