lcp.c \
magic.c \
main.c \
+ event-handler.c \
options.c \
session.c \
tty.c \
--- /dev/null
+/*
+ * event-handler.c - generic select() based event handler. Should be system
+ * independent.
+ *
+ * Copyright (c) 1994-2025 Paul Mackerras. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Derived from sys-linux.c and sys-solaris.c by Jaco Kroon <jaco@uls.co.za>.
+ */
+#include <limits.h>
+#include <stddef.h>
+#include <errno.h>
+#include <sys/select.h>
+
+#include "pppd.h"
+#include "pppd-private.h"
+
+struct event_handler {
+ struct event_handler* next;
+ int fd;
+ event_cb cb;
+ void* ctx;
+};
+
+static fd_set in_fds; /* set of fds that wait_input waits for */
+static int max_in_fd; /* highest fd set in in_fds */
+static struct event_handler* handlers;
+static int called_remove;
+
+/********************************************************************
+ *
+ * wait_input - wait until there is data available,
+ * for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+
+void wait_input(struct timeval *timo)
+{
+ fd_set ready, exc;
+ int n;
+ struct event_handler* h = handlers, *nh;
+
+ called_remove = 0;
+ ready = in_fds;
+ exc = in_fds;
+ n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
+ if (n < 0 && errno != EINTR)
+ fatal("select: %m");
+
+ while (h) {
+ nh = h->next;
+ if (FD_ISSET(h->fd, &ready)) {
+ FD_CLR(h->fd, &ready); /* clear so that if we need to re-iterate we won't call again */
+ h->cb(h->fd, h->ctx);
+
+ if (called_remove) {
+ nh = handlers;
+ called_remove = 0;
+ }
+ }
+ h = nh;
+ }
+}
+
+/*
+ * add_fd - add an fd to the set that wait_input waits for.
+ */
+void add_fd(int fd)
+{
+ if (fd >= FD_SETSIZE)
+ fatal("internal error: file descriptor too large (%d)", fd);
+ FD_SET(fd, &in_fds);
+ if (fd > max_in_fd)
+ max_in_fd = fd;
+}
+
+void add_fd_callback(int fd, event_cb cb, void* ctx)
+{
+ struct event_handler *n = malloc(sizeof(*n));
+ n->next = handlers;
+ n->fd = fd;
+ n->cb = cb;
+ n->ctx = ctx;
+ handlers = n;
+ add_fd(fd);
+}
+
+/*
+ * remove_fd - remove an fd from the set that wait_input waits for.
+ */
+void remove_fd(int fd)
+{
+ struct event_handler** h, *t;
+ FD_CLR(fd, &in_fds);
+
+ for (h = &handlers; *h; h = &(*h)->next) {
+ if (fd == (*h)->fd) {
+ called_remove = 1;
+ t = (*h)->next;
+ free(*h);
+ *h = t;
+ return;
+ }
+ }
+}
+
+void event_handler_init()
+{
+ FD_ZERO(&in_fds);
+ max_in_fd = 0;
+}
fd_devnull = i;
}
+ event_handler_init();
+
/*
* Initialize system-dependent stuff.
*/
int loop_chars(unsigned char *, int); /* process chars from loopback */
int loop_frame(unsigned char *, int); /* should we bring link up? */
+/* internal-only event handler procedures */
+void event_handler_init(void); /* initialize the event handler */
+void wait_input(struct timeval *);
+ /* Wait for input, with timeout */
+void add_fd(int); /* Add fd to set to wait for */
+
/* Procedures exported from sys-*.c */
void sys_init(void); /* Do system-dependent initialization */
void sys_cleanup(void); /* Restore system state before exiting */
void restore_tty(int); /* Restore port's original parameters */
void setdtr(int, int); /* Raise or lower port's DTR line */
void output(int, unsigned char *, int); /* Output a PPP packet */
-void wait_input(struct timeval *);
- /* Wait for input, with timeout */
-void add_fd(int); /* Add fd to set to wait for */
-void remove_fd(int); /* Remove fd from set to wait for */
int read_packet(unsigned char *); /* Read PPP packet */
int get_loop_output(void); /* Read pkts from loopback */
void tty_send_config(int, u_int32_t, int, int);
extern void (*snoop_recv_hook)(unsigned char *p, int len);
extern void (*snoop_send_hook)(unsigned char *p, int len);
+/* mechanism to setup event handlers */
+typedef void (*event_cb)(int fd, void* ctx); /* callback signature */
+void add_fd_callback(int, event_cb, void*); /* add fd with callback */
+void remove_fd(int); /* Remove fd from set to wait for */
+
#ifdef __cplusplus
}
#endif
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
-#include <limits.h>
/* This is in netdevice.h. However, this compile will fail miserably if
you attempt to include netdevice.h because it has so many references
static int chindex; /* channel index (new style driver) */
-static fd_set in_fds; /* set of fds that wait_input waits for */
-static int max_in_fd; /* highest fd set in in_fds */
-
static int has_proxy_arp = 0;
static int driver_version = 0;
static int driver_modification = 0;
if (sock6_fd < 0)
sock6_fd = -errno; /* save errno for later */
#endif
-
- FD_ZERO(&in_fds);
- max_in_fd = 0;
}
/********************************************************************
}
}
-/********************************************************************
- *
- * wait_input - wait until there is data available,
- * for the length of time specified by *timo (indefinite
- * if timo is NULL).
- */
-
-void wait_input(struct timeval *timo)
-{
- fd_set ready, exc;
- int n;
-
- ready = in_fds;
- exc = in_fds;
- n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
- if (n < 0 && errno != EINTR)
- fatal("select: %m");
-}
-
-/*
- * add_fd - add an fd to the set that wait_input waits for.
- */
-void add_fd(int fd)
-{
- if (fd >= FD_SETSIZE)
- fatal("internal error: file descriptor too large (%d)", fd);
- FD_SET(fd, &in_fds);
- if (fd > max_in_fd)
- max_in_fd = fd;
-}
-
-/*
- * remove_fd - remove an fd from the set that wait_input waits for.
- */
-void remove_fd(int fd)
-{
- FD_CLR(fd, &in_fds);
-}
-
/********************************************************************
*
extern u_char inpacket_buf[]; /* borrowed from main.c */
-#define MAX_POLLFDS 32
-static struct pollfd pollfds[MAX_POLLFDS];
-static int n_pollfds;
-
static int link_mtu, link_mru;
#define NMODULES 32
ioctl(ip6fd, I_PUNLINK, ip6muxid);
fatal("Can't link PPP device to IP (2): %m");
}
-
- n_pollfds = 0;
}
/*
}
-/*
- * wait_input - wait until there is data available,
- * for the length of time specified by *timo (indefinite
- * if timo is NULL).
- */
-void
-wait_input(struct timeval *timo)
-{
- int t;
-
- t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
- if (poll(pollfds, n_pollfds, t) < 0 && errno != EINTR)
- fatal("poll: %m");
-}
-
-/*
- * add_fd - add an fd to the set that wait_input waits for.
- */
-void add_fd(int fd)
-{
- int n;
-
- for (n = 0; n < n_pollfds; ++n)
- if (pollfds[n].fd == fd)
- return;
- if (n_pollfds < MAX_POLLFDS) {
- pollfds[n_pollfds].fd = fd;
- pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP;
- ++n_pollfds;
- } else
- error("Too many inputs!");
-}
-
-/*
- * remove_fd - remove an fd from the set that wait_input waits for.
- */
-void remove_fd(int fd)
-{
- int n;
-
- for (n = 0; n < n_pollfds; ++n) {
- if (pollfds[n].fd == fd) {
- while (++n < n_pollfds)
- pollfds[n-1] = pollfds[n];
- --n_pollfds;
- break;
- }
- }
-}
-
/*
* read_packet - get a PPP packet from the serial device.
*/