abduco

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

commit a8140f73d7ec15d8d7ac48844d20a93eb82151ea
parent 9fef960e264c1fade2a508a9525811fb5a4d6984
Author: Quentin Rameau <quinq@fifth.space>
Date:   Wed, 23 May 2018 12:53:28 +0200

Add m option to attach with maximum prority

This will let the user create a client session which will always
control the terminal size, over other clients.
This is the inverse function of l flag.

Diffstat:
abduco.1 | 2++
abduco.c | 36+++++++++++++++++++++++++++---------
client.c | 1+
debug.c | 1+
server.c | 20+++++++++++++++++++-
5 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/abduco.1 b/abduco.1 @@ -102,6 +102,8 @@ Force creation of session when there is an already terminated session of the sam after showing its exit status. .It Fl l Attach with the lowest priority, meaning this client will be the last to control the size. +.It Fl m +Attach with the maximum priority, meaning this client will always control the size. .It Fl p Pass through content of standard input to the session. Implies the .Fl q diff --git a/abduco.c b/abduco.c @@ -63,12 +63,13 @@ #define countof(arr) (sizeof(arr) / sizeof((arr)[0])) enum PacketType { - MSG_CONTENT = 0, - MSG_ATTACH = 1, - MSG_DETACH = 2, - MSG_RESIZE = 3, - MSG_EXIT = 4, - MSG_PID = 5, + MSG_CONTENT, + MSG_REFUSED, + MSG_ATTACH, + MSG_DETACH, + MSG_RESIZE, + MSG_EXIT, + MSG_PID, }; typedef struct { @@ -89,6 +90,7 @@ typedef struct Client Client; struct Client { int socket; enum { + STATE_REFUSED, STATE_CONNECTED, STATE_ATTACHED, STATE_DETACHED, @@ -98,6 +100,7 @@ struct Client { enum { CLIENT_READONLY = 1 << 0, CLIENT_LOWPRIORITY = 1 << 1, + CLIENT_MAXPRIORITY = 1 << 2, } flags; Client *next; }; @@ -107,6 +110,7 @@ typedef struct { int socket; Packet pty_output; int pty; + int has_maxprio; int exit_status; struct termios term; struct winsize winsize; @@ -118,7 +122,12 @@ typedef struct { bool read_pty; } Server; -static Server server = { .running = true, .exit_status = -1, .host = "@localhost" }; +static Server server = { + .running = true, + .exit_status = -1, + .host = "@localhost", + .has_maxprio = 0, + }; static Client client; static struct termios orig_term, cur_term; static bool has_term, alternate_buffer, quiet, passthrough; @@ -223,7 +232,8 @@ static void die(const char *s) { } static void usage(void) { - fprintf(stderr, "usage: abduco [-a|-A|-c|-n] [-p] [-r] [-q] [-l] [-f] [-e detachkey] name command\n"); + fprintf(stderr, "usage: abduco [-A|-a|-c|-n] [-p] [-r] [-q] [-l|-m] " + "[-f] [-e detachkey] name command\n"); exit(EXIT_FAILURE); } @@ -534,6 +544,8 @@ static bool attach_session(const char *name, const bool terminate) { client_restore_terminal(); if (status == -1) { info("detached"); + } else if (status == 222) { + info("server has already a max priority client"); } else if (status == -EIO) { info("exited due to I/O errors"); } else { @@ -606,7 +618,7 @@ int main(int argc, char *argv[]) { server.name = basename(argv[0]); gethostname(server.host+1, sizeof(server.host) - 1); - while ((opt = getopt(argc, argv, "aAclne:fpqrv")) != -1) { + while ((opt = getopt(argc, argv, "aAclmne:fpqrv")) != -1) { switch (opt) { case 'a': case 'A': @@ -636,6 +648,9 @@ int main(int argc, char *argv[]) { case 'l': client.flags |= CLIENT_LOWPRIORITY; break; + case 'm': + client.flags |= CLIENT_MAXPRIORITY; + break; case 'v': puts("abduco-"VERSION" © 2013-2018 Marc André Tanner"); exit(EXIT_SUCCESS); @@ -644,6 +659,9 @@ int main(int argc, char *argv[]) { } } + if ((client.flags & CLIENT_LOWPRIORITY) && (client.flags & CLIENT_MAXPRIORITY)) + usage(); + /* collect the session name if trailing args */ if (optind < argc) server.session_name = argv[optind]; diff --git a/client.c b/client.c @@ -106,6 +106,7 @@ static int client_mainloop(void) { case MSG_RESIZE: client.need_resize = true; break; + case MSG_REFUSED: case MSG_EXIT: client_send_packet(&pkt); close(server.socket); diff --git a/debug.c b/debug.c @@ -13,6 +13,7 @@ static void debug(const char *errstr, ...) { static void print_packet(const char *prefix, Packet *pkt) { static const char *msgtype[] = { [MSG_CONTENT] = "CONTENT", + [MSG_REFUSED] = "REFUSED", [MSG_ATTACH] = "ATTACH", [MSG_DETACH] = "DETACH", [MSG_RESIZE] = "RESIZE", diff --git a/server.c b/server.c @@ -224,8 +224,14 @@ static void server_mainloop(void) { break; case MSG_ATTACH: c->flags = client_packet.u.i; - if (c->flags & CLIENT_LOWPRIORITY) + if (c->flags & CLIENT_MAXPRIORITY) { + if (server.has_maxprio) + c->state = STATE_REFUSED; + else + server.has_maxprio = 222; + } else if (c->flags & CLIENT_LOWPRIORITY || server.has_maxprio) { server_sink_client(); + } break; case MSG_RESIZE: c->state = STATE_ATTACHED; @@ -249,6 +255,17 @@ static void server_mainloop(void) { } } + if (c->state == STATE_REFUSED) { + Packet pkt = { + .type = MSG_REFUSED, + .u.i = server.has_maxprio, + .len = sizeof(pkt.u.i), + }; + if (!server_send_packet(c, &pkt)) + FD_SET_MAX(c->socket, &new_writefds, new_fdmax); + continue; + } + if (c->state == STATE_DISCONNECTED) { bool first = (c == server.clients); Client *t = c->next; @@ -261,6 +278,7 @@ static void server_mainloop(void) { }; server_send_packet(server.clients, &pkt); } else if (!server.clients) { + server.has_maxprio = 0; server_mark_socket_exec(false, true); } continue;