59 lines
1.9 KiB
C
59 lines
1.9 KiB
C
// ctty-run: gibt dem Kindprozess ein Controlling-Terminal auf dem PTY-Slave.
|
|
// Usage: ctty-run <slave-pfad> <programm> [args...]
|
|
// stdin/stdout zeigen dabei bereits auf den Slave (vom Parent gesetzt),
|
|
// stderr bleibt unberührt (Eltern-Pipe für garantierte Fehlerausgabe).
|
|
//
|
|
// Warum Double-Fork: Apples Process startet Kinder in eigener Prozessgruppe,
|
|
// daher schlägt setsid() im direkten Kind mit EPERM fehl. Der Wächter forkt
|
|
// einmal weiter (Enkel = kein Leader mehr), wartet auf ihn und übernimmt
|
|
// dessen Exit-Code — Lifecycle/Exit-Codes bleiben für den Parent korrekt.
|
|
// Der Enkel: setsid() -> Slave einmal öffnen (wird dadurch Ctty) -> exec.
|
|
// Ohne Ctty scheitern ssh-Passwort- und Yes/No-Prompts still (/dev/tty ENXIO).
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <sys/wait.h>
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
if (argc < 3) {
|
|
dprintf(STDERR_FILENO, "usage: ctty-run <slave> <prog> [args...]\n");
|
|
return 2;
|
|
}
|
|
pid_t pid = fork();
|
|
if (pid < 0) {
|
|
dprintf(STDERR_FILENO, "ctty-run: fork: %s\n", strerror(errno));
|
|
return 1;
|
|
}
|
|
if (pid > 0) {
|
|
/* Wächter: keine FDs offen halten (sonst nie EOF), aufs Kind warten. */
|
|
close(STDIN_FILENO);
|
|
close(STDOUT_FILENO);
|
|
close(STDERR_FILENO);
|
|
int st = 0;
|
|
while (waitpid(pid, &st, 0) < 0 && errno == EINTR)
|
|
;
|
|
if (WIFEXITED(st))
|
|
return WEXITSTATUS(st);
|
|
return 128;
|
|
}
|
|
/* Enkel: eigene Session; danach Slave-Open = Ctty. */
|
|
if (setsid() < 0) {
|
|
dprintf(STDERR_FILENO, "ctty-run: setsid: %s (weiter ohne Ctty)\n",
|
|
strerror(errno));
|
|
}
|
|
int fd = open(argv[1], O_RDWR);
|
|
if (fd < 0) {
|
|
dprintf(STDERR_FILENO, "ctty-run: open slave: %s\n", strerror(errno));
|
|
_exit(1);
|
|
}
|
|
close(fd); /* Ctty bleibt der Session erhalten */
|
|
execvp(argv[2], &argv[2]);
|
|
dprintf(STDERR_FILENO, "ctty-run: execvp: %s\n", strerror(errno));
|
|
_exit(127);
|
|
}
|