mirror of
https://github.com/skeeto/endlessh.git
synced 2025-12-08 22:23:23 +00:00
Improve support for Solaris and its derivatives
Requires extensions to be enabled due to incomplete support for POSIX.1-2008. However one of the now-exposed extensions is tragically named "struct queue". This struct was been renamed to "struct fifo". Thanks to @yvoinov for reporting this issue and collaborating on a solution. Closes #14, #17.
This commit is contained in:
22
README.md
22
README.md
@@ -73,11 +73,27 @@ LogLevel 0
|
|||||||
|
|
||||||
## Build issues
|
## Build issues
|
||||||
|
|
||||||
RHEL 6 and CentOS 6 use a version of glibc older than 2.17 (December
|
Some more esoteric systems require extra configuration when building.
|
||||||
2012), and `clock_gettime(2)` is still in librt. For these systems you
|
|
||||||
will need to link against librt:
|
### RHEL 6 / CentOS 6
|
||||||
|
|
||||||
|
This system uses a version of glibc older than 2.17 (December 2012), and
|
||||||
|
`clock_gettime(2)` is still in librt. For these systems you will need to
|
||||||
|
link against librt:
|
||||||
|
|
||||||
make LDLIBS=-lrt
|
make LDLIBS=-lrt
|
||||||
|
|
||||||
|
### Solaris / illumos
|
||||||
|
|
||||||
|
These systems don't include all the necessary functionality in libc and
|
||||||
|
the linker requires some extra libraries:
|
||||||
|
|
||||||
|
make CC=gcc LDLIBS='-lnsl -lrt -lsocket'
|
||||||
|
|
||||||
|
If you're not using GCC or Clang, also override `CFLAGS` and `LDFLAGS`
|
||||||
|
to remove GCC-specific options. For example, on Solaris:
|
||||||
|
|
||||||
|
make CFLAGS=-fast LDFLAGS= LDLIBS='-lnsl -lrt -lsocket'
|
||||||
|
|
||||||
|
|
||||||
[np]: https://nullprogram.com/blog/2019/03/22/
|
[np]: https://nullprogram.com/blog/2019/03/22/
|
||||||
|
|||||||
42
endlessh.c
42
endlessh.c
@@ -1,4 +1,4 @@
|
|||||||
#ifdef __FreeBSD__
|
#if defined(__FreeBSD__)
|
||||||
# define _WITH_GETLINE
|
# define _WITH_GETLINE
|
||||||
/* The MSG_DONTWAIT send(2) flag is non-standard, but widely available.
|
/* The MSG_DONTWAIT send(2) flag is non-standard, but widely available.
|
||||||
* However, FreeBSD doesn't define this flag when using POSIX feature
|
* However, FreeBSD doesn't define this flag when using POSIX feature
|
||||||
@@ -13,6 +13,12 @@
|
|||||||
* test macro or use the FreeBSD-specific _WITH_GETLINE macro. Since we
|
* test macro or use the FreeBSD-specific _WITH_GETLINE macro. Since we
|
||||||
* can't use the former, we'll have to go with the latter.
|
* can't use the former, we'll have to go with the latter.
|
||||||
*/
|
*/
|
||||||
|
#elif defined(__sun__)
|
||||||
|
/* Solaris and its illumos derivatives consider getline(3) to be an
|
||||||
|
* extension despite this function being standardized by POSIX.1-2008
|
||||||
|
* more than a decade ago. As a workaround just enable all extensions.
|
||||||
|
*/
|
||||||
|
# define __EXTENSIONS__
|
||||||
#else
|
#else
|
||||||
# define _POSIX_C_SOURCE 200809L
|
# define _POSIX_C_SOURCE 200809L
|
||||||
#endif
|
#endif
|
||||||
@@ -149,21 +155,21 @@ client_destroy(struct client *client)
|
|||||||
free(client);
|
free(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct queue {
|
struct fifo {
|
||||||
struct client *head;
|
struct client *head;
|
||||||
struct client *tail;
|
struct client *tail;
|
||||||
int length;
|
int length;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_init(struct queue *q)
|
fifo_init(struct fifo *q)
|
||||||
{
|
{
|
||||||
q->head = q->tail = 0;
|
q->head = q->tail = 0;
|
||||||
q->length = 0;
|
q->length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct client *
|
static struct client *
|
||||||
queue_remove(struct queue *q, int fd)
|
fifo_remove(struct fifo *q, int fd)
|
||||||
{
|
{
|
||||||
/* Yes, this is a linear search, but the element we're looking for
|
/* Yes, this is a linear search, but the element we're looking for
|
||||||
* is virtually always one of the first few elements.
|
* is virtually always one of the first few elements.
|
||||||
@@ -190,7 +196,7 @@ queue_remove(struct queue *q, int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_append(struct queue *q, struct client *c)
|
fifo_append(struct fifo *q, struct client *c)
|
||||||
{
|
{
|
||||||
if (!q->tail) {
|
if (!q->tail) {
|
||||||
q->head = q->tail = c;
|
q->head = q->tail = c;
|
||||||
@@ -202,7 +208,7 @@ queue_append(struct queue *q, struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_destroy(struct queue *q)
|
fifo_destroy(struct fifo *q)
|
||||||
{
|
{
|
||||||
struct client *c = q->head;
|
struct client *c = q->head;
|
||||||
while (c) {
|
while (c) {
|
||||||
@@ -622,8 +628,8 @@ main(int argc, char **argv)
|
|||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct queue queue[1];
|
struct fifo fifo[1];
|
||||||
queue_init(queue);
|
fifo_init(fifo);
|
||||||
|
|
||||||
struct pollvec pollvec[1];
|
struct pollvec pollvec[1];
|
||||||
pollvec_init(pollvec);
|
pollvec_init(pollvec);
|
||||||
@@ -647,7 +653,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Enqueue the listening socket first */
|
/* Enqueue the listening socket first */
|
||||||
pollvec_clear(pollvec);
|
pollvec_clear(pollvec);
|
||||||
if (queue->length < config.max_clients)
|
if (fifo->length < config.max_clients)
|
||||||
pollvec_push(pollvec, server, POLLIN);
|
pollvec_push(pollvec, server, POLLIN);
|
||||||
else
|
else
|
||||||
pollvec_push(pollvec, -1, 0);
|
pollvec_push(pollvec, -1, 0);
|
||||||
@@ -655,7 +661,7 @@ main(int argc, char **argv)
|
|||||||
/* Enqueue clients that are due for another message */
|
/* Enqueue clients that are due for another message */
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
long long now = uepoch();
|
long long now = uepoch();
|
||||||
for (struct client *c = queue->head; c; c = c->next) {
|
for (struct client *c = fifo->head; c; c = c->next) {
|
||||||
if (c->send_next <= now) {
|
if (c->send_next <= now) {
|
||||||
pollvec_push(pollvec, c->fd, POLLOUT);
|
pollvec_push(pollvec, c->fd, POLLOUT);
|
||||||
} else {
|
} else {
|
||||||
@@ -666,7 +672,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Wait for next event */
|
/* Wait for next event */
|
||||||
logmsg(LOG_DEBUG, "poll(%zu, %d)%s", pollvec->fill, timeout,
|
logmsg(LOG_DEBUG, "poll(%zu, %d)%s", pollvec->fill, timeout,
|
||||||
queue->length >= config.max_clients ? " (no accept)" : "");
|
fifo->length >= config.max_clients ? " (no accept)" : "");
|
||||||
int r = poll(pollvec->fds, pollvec->fill, timeout);
|
int r = poll(pollvec->fds, pollvec->fill, timeout);
|
||||||
logmsg(LOG_DEBUG, "= %d", r);
|
logmsg(LOG_DEBUG, "= %d", r);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
@@ -689,10 +695,10 @@ main(int argc, char **argv)
|
|||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EMFILE:
|
case EMFILE:
|
||||||
case ENFILE:
|
case ENFILE:
|
||||||
config.max_clients = queue->length;
|
config.max_clients = fifo->length;
|
||||||
logmsg(LOG_INFO,
|
logmsg(LOG_INFO,
|
||||||
"MaxClients %d",
|
"MaxClients %d",
|
||||||
queue->length);
|
fifo->length);
|
||||||
break;
|
break;
|
||||||
case ECONNABORTED:
|
case ECONNABORTED:
|
||||||
case EINTR:
|
case EINTR:
|
||||||
@@ -712,10 +718,10 @@ main(int argc, char **argv)
|
|||||||
fprintf(stderr, "endlessh: warning: out of memory\n");
|
fprintf(stderr, "endlessh: warning: out of memory\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
queue_append(queue, client);
|
fifo_append(fifo, client);
|
||||||
logmsg(LOG_INFO, "ACCEPT host=%s port=%d fd=%d n=%d/%d",
|
logmsg(LOG_INFO, "ACCEPT host=%s port=%d fd=%d n=%d/%d",
|
||||||
client->ipaddr, client->port, client->fd,
|
client->ipaddr, client->port, client->fd,
|
||||||
queue->length, config.max_clients);
|
fifo->length, config.max_clients);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,7 +729,7 @@ main(int argc, char **argv)
|
|||||||
for (size_t i = 1; i < pollvec->fill; i++) {
|
for (size_t i = 1; i < pollvec->fill; i++) {
|
||||||
short fd = pollvec->fds[i].fd;
|
short fd = pollvec->fds[i].fd;
|
||||||
short revents = pollvec->fds[i].revents;
|
short revents = pollvec->fds[i].revents;
|
||||||
struct client *client = queue_remove(queue, fd);
|
struct client *client = fifo_remove(fifo, fd);
|
||||||
|
|
||||||
if (revents & POLLHUP) {
|
if (revents & POLLHUP) {
|
||||||
client_destroy(client);
|
client_destroy(client);
|
||||||
@@ -743,7 +749,7 @@ main(int argc, char **argv)
|
|||||||
logmsg(LOG_DEBUG, "send(%d) = %d", fd, (int)out);
|
logmsg(LOG_DEBUG, "send(%d) = %d", fd, (int)out);
|
||||||
client->bytes_sent += out;
|
client->bytes_sent += out;
|
||||||
client->send_next = uepoch() + config.delay;
|
client->send_next = uepoch() + config.delay;
|
||||||
queue_append(queue, client);
|
fifo_append(fifo, client);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -752,5 +758,5 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pollvec_free(pollvec);
|
pollvec_free(pollvec);
|
||||||
queue_destroy(queue);
|
fifo_destroy(fifo);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user