aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.c
blob: 94621c1852dd2d3819fb97cce22c0335e137d2f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* Entry point and argument parsing.
 *
 *   sl0ppty                  attach to session "main", creating it if needed
 *   sl0ppty -s NAME          ... a named session
 *   sl0ppty ls               live sessions
 *   sl0ppty cmd LINE         one control command against a session
 *   sl0ppty --server NAME    run a session in the foreground (internal)
 *   sl0ppty --script         the headless driver (no server, no tty)
 *   sl0ppty --headless       run once, print the screen
 */
#define _GNU_SOURCE
#include "sl0ppty.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>

#include "proto.h"
#include "server.h"

int run_headless(const char *const argv[], uint16_t cols, uint16_t rows,
                 int idle_ms, bool script, const char *layout);

static void term_size(uint16_t *cols, uint16_t *rows) {
  struct winsize ws;
  if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col && ws.ws_row) {
    *cols = ws.ws_col;
    *rows = ws.ws_row;
  } else {
    *cols = 80;
    *rows = 24;
  }
}

static void usage(void) {
  fputs("usage: sl0ppty [-s NAME] [--layout FILE] [ls | cmd LINE | -- CMD...]\n",
        stderr);
}

int main(int argc, char **argv) {
  bool headless = false, script = false, server = false;
  uint16_t cols = 80, rows = 24;
  int idle_ms = 300;
  const char *name = "main";
  const char *cmd_line = NULL;
  const char *layout = NULL;
  bool list = false;
  const char *cmd_argv[64];
  int cmd_n = 0;

  for (int i = 1; i < argc; i++) {
    const char *a = argv[i];
    if (strcmp(a, "--headless") == 0) headless = true;
    else if (strcmp(a, "--script") == 0) headless = script = true;
    else if (strcmp(a, "--server") == 0) server = true;
    else if (strcmp(a, "-s") == 0 && i + 1 < argc) name = argv[++i];
    else if (strcmp(a, "--layout") == 0 && i + 1 < argc) layout = argv[++i];
    else if (strcmp(a, "ls") == 0) list = true;
    else if (strcmp(a, "cmd") == 0 && i + 1 < argc) cmd_line = argv[++i];
    else if (strcmp(a, "--cols") == 0 && i + 1 < argc) cols = (uint16_t)atoi(argv[++i]);
    else if (strcmp(a, "--rows") == 0 && i + 1 < argc) rows = (uint16_t)atoi(argv[++i]);
    else if (strcmp(a, "--idle-ms") == 0 && i + 1 < argc) idle_ms = atoi(argv[++i]);
    else if (strcmp(a, "-h") == 0 || strcmp(a, "--help") == 0) {
      usage();
      return 0;
    } else if (strcmp(a, "--") == 0) {
      for (int j = i + 1; j < argc && cmd_n < 63; j++) cmd_argv[cmd_n++] = argv[j];
      break;
    } else {
      fprintf(stderr, "sl0ppty: unknown argument: %s\n", a);
      usage();
      return 2;
    }
  }

  if (cmd_n == 0) {
    const char *shell = getenv("SHELL");
    cmd_argv[cmd_n++] = shell && *shell ? shell : "/bin/sh";
  }
  cmd_argv[cmd_n] = NULL;

  if (list) {
    char **names = NULL;
    size_t n = session_list(&names);
    for (size_t i = 0; i < n; i++) {
      int fd = server_connect(names[i]);
      printf("%-20s %s\n", names[i], fd >= 0 ? "running" : "stale");
      if (fd >= 0) close(fd);
      free(names[i]);
    }
    free(names);
    return 0;
  }

  if (cmd_line) {
    int fd = server_connect(name);
    if (fd < 0) {
      fprintf(stderr, "sl0ppty: no session named %s\n", name);
      return 1;
    }
    return client_control(fd, cmd_line);
  }

  if (headless) return run_headless(cmd_argv, cols, rows, idle_ms, script, layout);

  if (isatty(STDOUT_FILENO)) term_size(&cols, &rows);
  if (server) return server_run(name, cmd_argv, cols, rows, layout);

  /* attach, creating the session if nobody is home */
  int fd = server_connect(name);
  if (fd < 0) fd = server_spawn(name, cmd_argv, cols, rows, layout);
  if (fd < 0) {
    fprintf(stderr, "sl0ppty: cannot start session %s\n", name);
    return 1;
  }
  return client_run(fd);
}