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
70 changes: 39 additions & 31 deletions attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ static void process_kbd(int s, struct packet *pkt)
else if (pkt->u.buf[0] == detach_char) {
char age[32];
session_age(age, sizeof(age));
pkt->type = MSG_DETACH;
write_packet_or_fail(s, pkt);
printf("%s[%s: session '%s' detached after %s]\r\n",
clear_csi_data(), progname, session_shortname(), age);
exit(0);
Expand Down Expand Up @@ -239,6 +241,10 @@ int replay_session_log(int saved_errno)
{
unsigned char rbuf[BUFSIZE];
ssize_t n;
struct stat st;

if (fstat(logfd, &st) == 0 && st.st_size > SCROLLBACK_SIZE)
lseek(logfd, st.st_size - SCROLLBACK_SIZE, SEEK_SET);

while ((n = read(logfd, rbuf, sizeof(rbuf))) > 0)
write(1, rbuf, (size_t)n);
Expand All @@ -263,10 +269,40 @@ int attach_main(int noerror)
fd_set readfds;
int s;

/* Attempt to open the socket. Don't display an error if noerror is
** set. */
s = connect_socket(sockname);
if (s < 0) {
int saved_errno = errno;
const char *name = session_shortname();

if (!noerror) {
if (saved_errno == ENOENT) {
printf
("%s: session '%s' does not exist\n",
progname, name);
} else if (!replay_session_log(saved_errno)) {
if (saved_errno == ECONNREFUSED)
printf
("%s: session '%s' is not running\n",
progname, name);
else if (saved_errno == ENOTSOCK)
printf
("%s: '%s' is not a valid session\n",
progname, name);
else
printf("%s: %s: %s\n", progname,
sockname, strerror(saved_errno));
}
}
return 1;
}

/* Refuse to attach to any session in our ancestry chain (catches both
* direct self-attach and indirect loops like A -> B -> A).
* SESSION_ENVVAR is the colon-separated chain, so scanning it covers
* all ancestors. */
* all ancestors. The check is done after connect so that a stale env
* var from a dead session does not block new attaches. */
{
const char *tosearch = getenv(SESSION_ENVVAR);

Expand All @@ -281,6 +317,7 @@ int attach_main(int noerror)

if (tlen == slen
&& strncmp(p, sockname, tlen) == 0) {
close(s);
if (!noerror)
printf
("%s: cannot attach to session '%s' from within itself\n",
Expand All @@ -295,35 +332,6 @@ int attach_main(int noerror)
}
}

/* Attempt to open the socket. Don't display an error if noerror is
** set. */
s = connect_socket(sockname);
if (s < 0) {
int saved_errno = errno;
const char *name = session_shortname();

if (!noerror) {
if (!replay_session_log(saved_errno)) {
if (saved_errno == ENOENT)
printf
("%s: session '%s' does not exist\n",
progname, name);
else if (saved_errno == ECONNREFUSED)
printf
("%s: session '%s' is not running\n",
progname, name);
else if (saved_errno == ENOTSOCK)
printf
("%s: '%s' is not a valid session\n",
progname, name);
else
printf("%s: %s: %s\n", progname,
sockname, strerror(saved_errno));
}
}
return 1;
}

/* Replay the on-disk log so the user sees full session history.
** Skip if already replayed by the error path (exited-session case). */
int skip_ring = 0;
Expand Down Expand Up @@ -373,7 +381,7 @@ int attach_main(int noerror)
** the separator: the log ends at the exact pty cursor position, so
** the prompt is already visible and correctly placed. */
if (clear_method == CLEAR_MOVE && !no_ansiterm) {
write_buf_or_fail(1, "\033c", 2);
write_buf_or_fail(1, "\033[H\033[2J\033[3J", 14);
} else if (!quiet && !skip_ring) {
write_buf_or_fail(1, "\r\n", 2);
}
Expand Down
10 changes: 8 additions & 2 deletions master.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,28 +248,34 @@ static int create_socket(char *name)

omask = umask(077);
s = socket(PF_UNIX, SOCK_STREAM, 0);
umask(omask); /* umask always succeeds, errno is untouched. */
if (s < 0)
if (s < 0) {
umask(omask);
return -1;
}
sockun.sun_family = AF_UNIX;
memcpy(sockun.sun_path, name, strlen(name) + 1);
if (bind(s, (struct sockaddr *)&sockun, sizeof(sockun)) < 0) {
close(s);
umask(omask);
return -1;
}
if (listen(s, 128) < 0) {
close(s);
umask(omask);
return -1;
}
if (setnonblocking(s) < 0) {
close(s);
umask(omask);
return -1;
}
/* chmod it to prevent any surprises */
if (chmod(name, 0600) < 0) {
close(s);
umask(omask);
return -1;
}
umask(omask);
return s;
}

Expand Down