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
20 changes: 15 additions & 5 deletions src/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,18 @@ struct Value *handle_lcd_command(String *args, int offset)
}

#if HAVE_GETCWD
oprintf("%% Current directory is %s", getcwd(buffer, PATH_MAX));
if (!getcwd(buffer, sizeof(buffer))) {
operror("getcwd");
return shareval(val_zero);
}
oprintf("%% Current directory is %s", buffer);
#else
# if HAVE_GETWD
oprintf("%% Current directory is %s", getwd(buffer));
if (!getwd(buffer)) {
operror("getwd");
return shareval(val_zero);
}
oprintf("%% Current directory is %s", buffer);
# endif
#endif
return shareval(val_one);
Expand Down Expand Up @@ -359,8 +367,11 @@ int handle_echo_func(
return 0;
}
if (raw) {
write(STDOUT_FILENO, src->data, src->len);
return 1;
if (write_full(STDOUT_FILENO, src->data, src->len) < 0) {
operror("write");
return 0;
}
return 1;
}

newstr = inline_flag ? CS(decode_attr(src, 0, 0)) : CS(Stringdup(src));
Expand Down Expand Up @@ -823,4 +834,3 @@ struct Value *handle_bind_command(String *args, int offset)
return newint(add_new_macro(NULL, print_to_ascii(NULL, pattern)->data,
NULL, NULL, body, 1, 100, 0, FALSE, 0));
}

8 changes: 6 additions & 2 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,12 @@ void bufflush(void)
n = outbuf->len - written;
if (n > 2048)
n = 2048;
result = write(STDOUT_FILENO, outbuf->data + written, n);
if (result < 0) break;
RETRY_ON_EINTR(result, write(STDOUT_FILENO,
outbuf->data + written, n));
if (result < 0)
break;
if (result == 0)
break;
written += result;
}
Stringtrunc(outbuf, 0);
Expand Down
5 changes: 5 additions & 0 deletions src/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ extern int errno; /* Some systems don't declare errno in errno.h. Duh. */

#include <stdio.h>

#define RETRY_ON_EINTR(result, expr) \
do { \
(result) = (expr); \
} while ((result) == -1 && errno == EINTR)

#ifndef SEEK_SET
# define SEEK_SET 0
#endif
Expand Down
6 changes: 4 additions & 2 deletions src/signals.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,11 @@ void init_exename(char *name)
{
argv0 = name;
#if HAVE_GETCWD
getcwd(initial_dir, PATH_MAX);
if (!getcwd(initial_dir, sizeof(initial_dir)))
initial_dir[0] = '\0';
#elif HAVE_GETWD
getwd(initial_dir);
if (!getwd(initial_dir))
initial_dir[0] = '\0';
#endif
initial_path = getenv("PATH");
}
Expand Down
103 changes: 66 additions & 37 deletions src/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ static Sock *find_sock(const char *name);
static void wload(World *w);
static int fg_sock(Sock *sock, int quiet);
static int get_host_address(Sock *sock, const char **what, int *errp);
#ifdef NONBLOCKING_GETHOST
static void close_resolver(Sock *sock);
#endif
#if !HAVE_GETADDRINFO
static int tfgetaddrinfo(const char *nodename, const char *port,
const struct addrinfo *hints, struct addrinfo **res);
Expand Down Expand Up @@ -1491,6 +1494,29 @@ static int ICONFAIL(Sock *sock, const char *what, const char *why)
return 0;
}

#ifdef NONBLOCKING_GETHOST
static void close_resolver(Sock *sock)
{
#ifdef PLATFORM_UNIX
pid_t pid;
#endif /* PLATFORM_UNIX */

if (sock->fd >= 0) {
close(sock->fd);
sock->fd = -1;
}
#ifdef PLATFORM_UNIX
if (sock->pid >= 0) {
RETRY_ON_EINTR(pid, waitpid(sock->pid, NULL, 0));
if (pid < 0)
tfprintf(tferr, "waitpid %ld: %s", (long)sock->pid,
strerror(errno));
sock->pid = -1;
}
#endif /* PLATFORM_UNIX */
}
#endif

static int openconn(Sock *sock)
{
int flags;
Expand All @@ -1500,41 +1526,34 @@ static int openconn(Sock *sock)
if (xsock->constate == SS_RESOLVING) {
nbgai_hdr_t info = { 0, 0 };
struct addrinfo *ai;
FD_CLR(xsock->fd, &readers);
if (read(xsock->fd, &info, sizeof(info)) < 0 || info.err != 0) {
if (!info.err)
CONFAIL(xsock, "read", strerror(errno));
else
CONFAILHP(xsock, gai_strerror(info.err));
if (xsock->fd >= 0) {
close(xsock->fd);
xsock->fd = -1;
}
# ifdef PLATFORM_UNIX
if (xsock->pid >= 0)
if (waitpid(xsock->pid, NULL, 0) < 0)
tfprintf(tferr, "waitpid %ld: %s", xsock->pid, strerror(errno));
xsock->pid = -1;
# endif /* PLATFORM_UNIX */
killsock(xsock);
return 0;
}
FD_CLR(xsock->fd, &readers);
if (read_full(xsock->fd, (char *)&info, sizeof(info)) < 0) {
CONFAIL(xsock, "read", strerror(errno));
close_resolver(xsock);
killsock(xsock);
return 0;
}
if (info.err != 0) {
CONFAILHP(xsock, gai_strerror(info.err));
close_resolver(xsock);
killsock(xsock);
return 0;
}
if (info.size <= 0) { /* shouldn't happen */
xsock->addrs = NULL;
} else {
xsock->addrs = XMALLOC(info.size);
read(xsock->fd, (char*)xsock->addrs, info.size);
if (read_full(xsock->fd, (char *)xsock->addrs, info.size) < 0) {
CONFAIL(xsock, "read", strerror(errno));
FREE(xsock->addrs);
xsock->addrs = NULL;
close_resolver(xsock);
killsock(xsock);
return 0;
}
}
if (xsock->fd >= 0) {
close(xsock->fd);
}
# ifdef PLATFORM_UNIX
if (xsock->pid >= 0)
if (waitpid(xsock->pid, NULL, 0) < 0)
tfprintf(tferr, "waitpid: %ld: %s", xsock->pid, strerror(errno));
xsock->pid = -1;
# endif /* PLATFORM_UNIX */
xsock->constate = SS_RESOLVED;
close_resolver(xsock);
xsock->constate = SS_RESOLVED;
for (ai = xsock->addrs; ai; ai = ai->ai_next) {
ai->ai_addr = (struct sockaddr*)((char*)ai + sizeof(*ai));
if (ai->ai_next != 0) {
Expand Down Expand Up @@ -1851,11 +1870,13 @@ static void waitforhostname(int fd, const char *name, const char *port)
iov[niov].iov_len = ai->ai_addrlen;
niov++;
}
writev(fd, iov, niov);
(void)writev_full(fd, iov, niov);
if (res) freeaddrinfo(res);
} else {
hdr.size = 0;
write(fd, &hdr, sizeof(hdr));
iov[0].iov_base = (char *)&hdr;
iov[0].iov_len = sizeof(hdr);
(void)writev_full(fd, iov, 1);
}
close(fd);
}
Expand Down Expand Up @@ -1954,9 +1975,13 @@ static int establish(Sock *sock)
} else if ((ai_connect(xsock->fd, xsock->addr) < 0) &&
errno != EISCONN)
{
read(xsock->fd, &ch, 1); /* must fail */
return ICONFAIL(xsock, "nonblocking connect 2/read", strerror(errno));
}
int connect_err = errno;
if (read(xsock->fd, &ch, 1) < 0) /* must fail */
return ICONFAIL(xsock, "nonblocking connect 2/read",
strerror(errno));
return ICONFAIL(xsock, "nonblocking connect 2",
strerror(connect_err));
}
}
#endif
if (err != 0) {
Expand Down Expand Up @@ -2115,9 +2140,13 @@ static void killsock(Sock *sock)
#ifdef NONBLOCKING_GETHOST
# ifdef PLATFORM_UNIX
if (sock->pid >= 0) {
pid_t pid;

kill(sock->pid, SIGTERM);
if (waitpid(sock->pid, NULL, 0) < 0)
tfprintf(tferr, "waitpid: %ld: %s", sock->pid, strerror(errno));
RETRY_ON_EINTR(pid, waitpid(sock->pid, NULL, 0));
if (pid < 0)
tfprintf(tferr, "waitpid: %ld: %s", (long)sock->pid,
strerror(errno));
sock->pid = -1;
}
# endif /* PLATFORM_UNIX */
Expand Down
32 changes: 25 additions & 7 deletions src/tfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -788,11 +788,27 @@ char igetchar(void)
{
char c;
fd_set readers;
int result;

FD_ZERO(&readers);
FD_SET(STDIN_FILENO, &readers);
while(select(1, &readers, NULL, NULL, NULL) <= 0);
read(STDIN_FILENO, &c, 1);
for (;;) {
FD_ZERO(&readers);
FD_SET(STDIN_FILENO, &readers);
result = select(STDIN_FILENO + 1, &readers, NULL, NULL, NULL);
if (result > 0)
break;
if (result < 0) {
if (errno == EINTR)
continue;
operror("select");
return '\0';
}
}
RETRY_ON_EINTR(result, read(STDIN_FILENO, &c, 1));
if (result != 1) {
if (result < 0)
operror("read");
return '\0';
}
return c;
}

Expand Down Expand Up @@ -900,8 +916,11 @@ String *tfgetS(String *str, TFILE *file)
file->off = next;
}
file->off = 0;
file->len = read(fileno(file->u.fp), file->buf, sizeof(file->buf));
} while (file->len > 0);
RETRY_ON_EINTR(file->len, read(fileno(file->u.fp), file->buf,
sizeof(file->buf)));
if (file->len < 0)
operror("read");
} while (file->len > 0);

file->len = -1; /* note eof */
return str->len ? str : NULL;
Expand Down Expand Up @@ -1004,4 +1023,3 @@ struct Value *handle_liststreams_command(String *args, int offset)

return newint(count);
}

67 changes: 67 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <limits.h>
#include "port.h"
#include "tf.h"
Expand Down Expand Up @@ -81,6 +82,72 @@ struct feature features[] = {

static void free_maillist(void);

int read_full(int fd, char *buf, size_t len)
{
size_t off = 0;

while (off < len) {
ssize_t result;

RETRY_ON_EINTR(result, read(fd, buf + off, len - off));
if (result < 0)
return -1;
if (result == 0) {
errno = EIO;
return -1;
}
off += result;
}
return 0;
}

int write_full(int fd, const char *buf, size_t len)
{
size_t off = 0;

while (off < len) {
ssize_t result;

RETRY_ON_EINTR(result, write(fd, buf + off, len - off));
if (result < 0)
return -1;
if (result == 0) {
errno = EIO;
return -1;
}
off += result;
}
return 0;
}

int writev_full(int fd, struct iovec *iov, int niov)
{
while (niov > 0) {
ssize_t result;
size_t written;

RETRY_ON_EINTR(result, writev(fd, iov, niov));
if (result < 0)
return -1;
if (result == 0) {
errno = EIO;
return -1;
}
Comment on lines +125 to +135

written = result;
while (niov > 0 && written >= iov[0].iov_len) {
written -= iov[0].iov_len;
iov++;
niov--;
}
if (niov > 0 && written > 0) {
iov[0].iov_base = (char *)iov[0].iov_base + written;
iov[0].iov_len -= written;
}
}
return 0;
}

#if !STDC_HEADERS
int lcase(x) char x; { return is_upper(x) ? tolower(x) : x; }
int ucase(x) char x; { return is_lower(x) ? toupper(x) : x; }
Expand Down
6 changes: 6 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ struct feature {
const int *flag;
};

struct iovec;

#undef CTRL
/* convert to or from ctrl character */
#define CTRL(c) (ucase(c) ^ '@')
Expand Down Expand Up @@ -101,6 +103,10 @@ extern const conString* print_to_ascii(String *buf, const char *str);
extern const conString* ascii_to_print(const char *str);
extern char *cstrchr(const char *s, int c);
extern char *estrchr(const char *s, int c, int e);
extern int read_full(int fd, char *buf, size_t len);
extern int write_full(int fd, const char *buf, size_t len);
/* writev_full() mutates iov while advancing through partial writes. */
extern int writev_full(int fd, struct iovec *iov, int niov);
extern int numarg(const char **str);
extern int nullstrcmp(const char *s, const char *t);
extern int nullcstrcmp(const char *s, const char *t);
Expand Down
Loading