Skip to content

Commit

Permalink
Add foreground mode with -F
Browse files Browse the repository at this point in the history
  • Loading branch information
nviennot committed Nov 4, 2019
1 parent 7f693a9 commit 6e84bab
Show file tree
Hide file tree
Showing 14 changed files with 196 additions and 38 deletions.
18 changes: 18 additions & 0 deletions cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,20 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
return (found);
}

static void print_cfg_errors(void)
{
u_int i;

for (i = 0; i < cfg_ncauses; i++) {
tmate_info("%s", cfg_causes[i]);
free(cfg_causes[i]);
}

free(cfg_causes);
cfg_causes = NULL;
cfg_ncauses = 0;
}

void
cfg_default_done(__unused struct cmd_q *cmdq)
{
Expand All @@ -158,6 +172,10 @@ cfg_default_done(__unused struct cmd_q *cmdq)

#ifdef TMATE
tmate_session_start();
if (tmate_foreground && cfg_ncauses) {
print_cfg_errors();
exit(1);
}
#endif

if (!RB_EMPTY(&sessions))
Expand Down
51 changes: 51 additions & 0 deletions client.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <unistd.h>

#include "tmux.h"
#include "tmate.h"

struct tmuxproc *client_proc;
struct tmuxpeer *client_peer;
Expand Down Expand Up @@ -213,8 +214,56 @@ client_exit_message(void)
#ifdef TMATE
extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_new_session_entry;

/* For foreground mode */
static int __argc;
static char **__argv;
#endif

static void _run_initial_client_cmd(int argc, char **argv)
{
struct cmd_q *cmd_q;
struct cmd_list *cmdlist;
char *cause;
const char *default_argv[] = {"new-session"};

if (argc == 0) {
argc = 1;
argv = (char **)default_argv;
}

cmd_q = cmdq_new(NULL); /* No client */

if ((cmdlist = cmd_list_parse(argc, (char **)argv, NULL, 0, &cause)) == NULL) {
tmate_fatal("%s", cause);
}

cmdq_run(cmd_q, cmdlist, NULL);
cmd_list_free(cmdlist);
cmdq_free(cmd_q);

/* error messages land in cfg_causes */
extern char **cfg_causes;
extern u_int cfg_ncauses;
int has_error = !!cfg_ncauses;
for (u_int i = 0; i < cfg_ncauses; i++) {
tmate_info("%s", cfg_causes[i]);
free(cfg_causes[i]);
}

free(cfg_causes);
cfg_causes = NULL;
cfg_ncauses = 0;

if (has_error)
exit(1);
}

void run_initial_client_cmd(void)
{
_run_initial_client_cmd(__argc, __argv);
}

/* Client main loop. */
int
client_main(struct event_base *base, int argc, char **argv, int flags,
Expand All @@ -232,6 +281,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
size_t size;
#ifdef TMATE
int cant_nest = 0;
__argc = argc;
__argv = argv;
#endif

/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
Expand Down
3 changes: 3 additions & 0 deletions cmd-new-session.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (c == NULL)
detached = 1;

if (tmate_foreground)
detached = 1;

/* Is this client already attached? */
already_attached = 0;
if (c != NULL && c->session != NULL)
Expand Down
49 changes: 35 additions & 14 deletions log.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ static int log_level;
static void log_event_cb(int, const char *);
static void log_vwrite(const char *, va_list);

static int is_log_stdout(void)
{
return fileno(log_file) <= 2;
}

/* Log callback for libevent. */
static void
log_event_cb(__unused int severity, const char *msg)
Expand All @@ -53,6 +58,18 @@ log_get_level(void)
return (log_level);
}

void
log_open_fp(FILE *f)
{
if (log_file != NULL && !is_log_stdout())
fclose(log_file);

log_file = f;

setvbuf(log_file, NULL, _IOLBF, 0);
event_set_log_callback(log_event_cb);
}

/* Open logging to file. */
void
log_open(const char *name)
Expand All @@ -62,24 +79,18 @@ log_open(const char *name)
if (log_level == 0)
return;

if (log_file != NULL)
fclose(log_file);

xasprintf(&path, "tmate-%s-%ld.log", name, (long)getpid());
log_file = fopen(path, "w");
FILE *f = fopen(path, "w");
free(path);
if (log_file == NULL)
return;

setvbuf(log_file, NULL, _IOLBF, 0);
event_set_log_callback(log_event_cb);
if (f)
log_open_fp(f);
}

/* Close logging. */
void
log_close(void)
{
if (log_file != NULL)
if (log_file != NULL && !is_log_stdout())
fclose(log_file);
log_file = NULL;

Expand All @@ -102,9 +113,16 @@ log_vwrite(const char *msg, va_list ap)
exit(1);

gettimeofday(&tv, NULL);
if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec,
(int)tv.tv_usec, out) == -1)
exit(1);

if (is_log_stdout()) {
if (fprintf(log_file, "%s\n", out) == -1)
exit(1);
} else {
if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec,
(int)tv.tv_usec, out) == -1)
exit(1);
}

fflush(log_file);

free(out);
Expand All @@ -113,10 +131,13 @@ log_vwrite(const char *msg, va_list ap)

/* Log a debug message. */
void
log_debug(const char *msg, ...)
log_emit(int level, const char *msg, ...)
{
va_list ap;

if (log_level < level)
return;

va_start(ap, msg);
log_vwrite(msg, ap);
va_end(ap);
Expand Down
10 changes: 8 additions & 2 deletions proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ proc_start(const char *name, struct event_base *base, int forkflag,
struct tmuxproc *tp;
struct utsname u;

if (forkflag) {
if (forkflag && !tmate_foreground) {
switch (fork()) {
case -1:
fatal("fork failed");
Expand All @@ -189,7 +189,13 @@ proc_start(const char *name, struct event_base *base, int forkflag,
fatalx("event_reinit failed");
}

log_open(name);
if (tmate_foreground) {
if (forkflag)
clear_signals(0);
log_open_fp(stdout);
} else {
log_open(name);
}

#ifdef HAVE_SETPROCTITLE
setproctitle("%s (%s)", name, socket_path);
Expand Down
14 changes: 11 additions & 3 deletions server.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,16 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
{
int pair[2];

if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
fatal("socketpair failed");
if (!tmate_foreground)
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
fatal("socketpair failed");

server_proc = proc_start("server", base, 1, server_signal);
if (server_proc == NULL) {
close(pair[1]);
return (pair[0]);
}

close(pair[0]);

if (log_get_level() > 3)
Expand Down Expand Up @@ -190,7 +192,8 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
if (server_fd == -1)
fatal("couldn't create socket");
server_update_socket();
server_client_create(pair[1]);
if (!tmate_foreground)
server_client_create(pair[1]);

if (lockfd >= 0) {
unlink(lockfile);
Expand All @@ -207,11 +210,15 @@ server_start(struct event_base *base, int lockfd, char *lockfile)

server_add_accept(0);

if (tmate_foreground)
run_initial_client_cmd();

proc_loop(server_proc, server_loop);
status_prompt_save_history();
#ifdef TMATE
unlink(socket_path);
#endif

exit(0);
}

Expand Down Expand Up @@ -361,6 +368,7 @@ server_signal(int sig)
int fd;

switch (sig) {
case SIGINT:
case SIGTERM:
server_exit = 1;
server_send_exit();
Expand Down
21 changes: 17 additions & 4 deletions session.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,6 @@ session_destroy(struct session *s)

log_debug("session %s destroyed", s->name);

#ifdef TMATE
tmate_write_fin();
#endif

RB_REMOVE(sessions, &sessions, s);
notify_session_closed(s);

Expand All @@ -240,6 +236,23 @@ session_destroy(struct session *s)
free((void *)s->cwd);

session_unref(s);

#ifdef TMATE
if (tmate_foreground && !server_exit) {
tmate_info("Shell exited, restarting");
/*
* throttle restarts. This is a blocking sleep.
* It's simpler than using a timer, but fairly harmless
* from a blocking perspective.
*/
usleep(500*1000);
next_session_id = 0;
run_initial_client_cmd();
} else {
tmate_info("Session terminated");
tmate_write_fin();
}
#endif
}

/* Check a session name is valid: not empty and no colons or periods. */
Expand Down
18 changes: 18 additions & 0 deletions signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "tmux.h"

struct event ev_sigint;
struct event ev_sighup;
struct event ev_sigchld;
struct event ev_sigcont;
Expand All @@ -40,15 +41,23 @@ set_signals(void (*handler)(int, short, void *), void *arg)
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_IGN;
#ifndef TMATE
if (sigaction(SIGINT, &sigact, NULL) != 0)
fatal("sigaction failed");
#endif
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
fatal("sigaction failed");
#ifndef TMATE
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
#endif

#ifdef TMATE
signal_set(&ev_sigint, SIGINT, handler, arg);
signal_add(&ev_sigint, NULL);
#endif
signal_set(&ev_sighup, SIGHUP, handler, arg);
signal_add(&ev_sighup, NULL);
signal_set(&ev_sigchld, SIGCHLD, handler, arg);
Expand All @@ -72,16 +81,24 @@ clear_signals(int after_fork)
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_DFL;
#ifndef TMATE
if (sigaction(SIGINT, &sigact, NULL) != 0)
fatal("sigaction failed");
#endif
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
fatal("sigaction failed");
#ifndef TMATE
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
#endif

if (after_fork) {
#ifdef TMATE
if (sigaction(SIGINT, &sigact, NULL) != 0)
fatal("sigaction failed");
#endif
if (sigaction(SIGHUP, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGCHLD, &sigact, NULL) != 0)
Expand All @@ -95,6 +112,7 @@ clear_signals(int after_fork)
if (sigaction(SIGWINCH, &sigact, NULL) != 0)
fatal("sigaction failed");
} else {
event_del(&ev_sigint);
event_del(&ev_sighup);
event_del(&ev_sigchld);
event_del(&ev_sigcont);
Expand Down
2 changes: 1 addition & 1 deletion tmate-msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void __tmate_status_message(const char *fmt, va_list ap)
char *message;

xvasprintf(&message, fmt, ap);
tmate_debug("%s", message);
tmate_info("%s", message);

TAILQ_FOREACH(c, &clients, entry) {
if (c && !(c->flags & CLIENT_READONLY))
Expand Down
Loading

0 comments on commit 6e84bab

Please sign in to comment.