diff --git a/atch.c b/atch.c index ff8f2f1..c0a7c2b 100644 --- a/atch.c +++ b/atch.c @@ -76,11 +76,17 @@ int socket_with_chdir(char *path, int (*fn)(char *)) *slash = '\0'; s = chdir(path) >= 0 ? fn(slash + 1) : -1; *slash = '/'; - if (s >= 0 && fchdir(dirfd) < 0) { - close(s); - s = -1; + /* Always restore cwd, regardless of socket operation result */ + { + int saved_errno = errno; + if (fchdir(dirfd) < 0) { + if (s >= 0) close(s); + close(dirfd); + return -1; + } + close(dirfd); + errno = saved_errno; } - close(dirfd); return s; } @@ -275,6 +281,10 @@ static void expand_sockname(void) mkdir(dir, 0700); fulllen = strlen(dir) + 1 + strlen(sockname); full = malloc(fulllen + 1); + if (!full) { + printf("%s: out of memory\n", progname); + exit(1); + } snprintf(full, fulllen + 1, "%s/%s", dir, sockname); sockname = full; } diff --git a/master.c b/master.c index 16f29e3..20a5971 100644 --- a/master.c +++ b/master.c @@ -58,6 +58,9 @@ static void rotate_log(void) char *buf; ssize_t n; + if (log_fd < 0) + return; + size = lseek(log_fd, 0, SEEK_END); if (size > (off_t) log_max_size) { buf = malloc(log_max_size); @@ -67,12 +70,18 @@ static void rotate_log(void) if (n > 0) { ftruncate(log_fd, 0); lseek(log_fd, 0, SEEK_SET); - write(log_fd, buf, (size_t)n); + if (write(log_fd, buf, (size_t)n) < 0) { + close(log_fd); + log_fd = -1; + free(buf); + return; + } } free(buf); } } - lseek(log_fd, 0, SEEK_END); + if (log_fd >= 0) + lseek(log_fd, 0, SEEK_END); } /* @@ -89,7 +98,7 @@ static int open_log(const char *path) log_fd = fd; rotate_log(); - return fd; + return log_fd; } /* Write end marker to log, close it, and unlink the socket. */ @@ -388,7 +397,12 @@ static void pty_activity(int s) } scrollback_append(buf, (size_t)len); if (log_fd >= 0) { - write(log_fd, buf, (size_t)len); + if (write(log_fd, buf, (size_t)len) < 0) { + close(log_fd); + log_fd = -1; + } + } + if (log_fd >= 0) { log_written += (size_t)len; if (log_written >= log_max_size) { rotate_log(); diff --git a/tests/test.sh b/tests/test.sh index 0c954c0..0c6fa14 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -720,6 +720,21 @@ assert_contains "no args: shows Usage:" "Usage:" "$out" run "$ATCH" --help assert_contains "help: shows tail command" "tail" "$out" +# ── 23. cwd preserved after socket failure ───────────────────────────────── +# socket_with_chdir must restore cwd even when the socket operation fails. +# We create the parent dir so chdir succeeds, but the session path is bogus. + +ORIG_PWD=$(pwd) +mkdir -p "$TESTDIR/sockdir" +"$ATCH" kill "$TESTDIR/sockdir/bogus" >/dev/null 2>&1 +AFTER_PWD=$(pwd) +if [ "$ORIG_PWD" = "$AFTER_PWD" ]; then + ok "cwd: preserved after failed socket operation" +else + fail "cwd: preserved after failed socket operation" "$ORIG_PWD" "$AFTER_PWD" + cd "$ORIG_PWD" +fi + # ── summary ────────────────────────────────────────────────────────────────── printf "\n1..%d\n" "$T"