Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ If no command is given, `$SHELL` is used.
| `kill [-f] <session>` | Gracefully stop a session (SIGTERM, then SIGKILL after 5 s if needed). With `-f` / `--force`, skip the grace period and send SIGKILL immediately. |
| `clear [<session>]` | Truncate the on-disk session log. Defaults to the current session when run inside one. |
| `tail [-f] [-n N] <session>` | Print the last N lines of the session log (default: 10). With `-f`, follow new output as it is written. |
| `list` | List all sessions. Shows `[attached]` when a client is connected, `[stale]` for leftover sockets with no running master. Prints `(no sessions)` when the list is empty. |
| `list [-a]` | List sessions. Shows `[attached]` when a client is connected, `[stale]` for leftover sockets with no running master. With `-a`, also shows `[exited]` sessions that have a log file but are no longer running. Prints `(no sessions)` when the list is empty. |
| `current` | Print the current session name and exit 0 if inside a session; exit 1 silently if not. |

Short aliases: `a` → `attach`, `n` → `new`, `s` → `start`, `p` → `push`,
Expand Down
19 changes: 13 additions & 6 deletions atch.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,17 @@ static int is_cmd(const char *arg, const char *a, const char *b, const char *c)
(b && strcmp(arg, b) == 0) || (c && strcmp(arg, c) == 0);
}

/* atch list */
static int cmd_list(void)
/* atch list [-a] */
static int cmd_list(int argc, char **argv)
{
return list_main();
int show_all = 0;

while (argc >= 1 && strcmp(argv[0], "-a") == 0) {
show_all = 1;
argc--;
argv++;
}
return list_main(show_all);
}

/* atch current
Expand Down Expand Up @@ -709,7 +716,7 @@ static void usage(void)
"\tPrint last N lines of session log\n"
" -f\t\t\t\tFollow log output\n"
" -n <lines>\t\t\tNumber of lines (default 10)\n"
" list\t\t\t\t\tList all sessions\n"
" list [-a]\t\t\t\tList sessions (-a includes exited)\n"
" current\t\t\t\tPrint current session name\n"
"\n"
"Options:\n"
Expand Down Expand Up @@ -781,7 +788,7 @@ int main(int argc, char **argv)
if (mode == '?' || mode == 'h')
usage();
if (mode == 'l')
return cmd_list();
return cmd_list(argc, argv);
if (mode == 'i')
return cmd_current();
if (mode != 'a' && mode != 'A' && mode != 'c' &&
Expand Down Expand Up @@ -876,7 +883,7 @@ int main(int argc, char **argv)
--argc;

if (is_cmd(cmd, "list", "l", "ls"))
return cmd_list();
return cmd_list(argc, argv);
if (is_cmd(cmd, "current", NULL, NULL))
return cmd_current();
if (is_cmd(cmd, "attach", "a", NULL))
Expand Down
2 changes: 1 addition & 1 deletion atch.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ int replay_session_log(int saved_errno);
int attach_main(int noerror);
int master_main(char **argv, int waitattach, int dontfork);
int push_main(void);
int list_main(void);
int list_main(int show_all);
int kill_main(int force);

char const * clear_csi_data(void);
Expand Down
40 changes: 39 additions & 1 deletion attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ int kill_main(int force)
return 1;
}

int list_main(void)
int list_main(int show_all)
{
char dir[512];
char path[768]; /* sizeof(dir) + '/' + NAME_MAX */
Expand Down Expand Up @@ -656,6 +656,44 @@ int list_main(void)

closedir(d);

/* Second pass: show exited sessions (log files without a socket). */
if (show_all) {
d = opendir(dir);
if (d) {
while ((ent = readdir(d)) != NULL) {
struct stat lst;
char age[32];
size_t nlen = strlen(ent->d_name);

if (nlen <= 4 ||
strcmp(ent->d_name + nlen - 4, ".log") != 0)
continue;

/* Build socket path (name without .log). */
snprintf(path, sizeof(path), "%s/%.*s",
dir, (int)(nlen - 4), ent->d_name);

/* Skip if the socket still exists (already listed). */
if (access(path, F_OK) == 0)
continue;

/* Stat the log file for its mtime. */
snprintf(path, sizeof(path), "%s/%s",
dir, ent->d_name);
if (stat(path, &lst) < 0)
continue;

format_age(now > lst.st_mtime ?
now - lst.st_mtime : 0,
age, sizeof(age));
printf("%-24.*s since %s ago [exited]\n",
(int)(nlen - 4), ent->d_name, age);
count++;
}
closedir(d);
}
}

empty:
if (count == 0 && !quiet)
printf("(no sessions)\n");
Expand Down