Skip to content

Instantly share code, notes, and snippets.

@splhack
Created July 7, 2009 13:47
Show Gist options
  • Save splhack/142081 to your computer and use it in GitHub Desktop.
Save splhack/142081 to your computer and use it in GitHub Desktop.
diff --git a/autoload/fakepoll.h b/autoload/fakepoll.h
new file mode 100644
index 0000000..2b2bac7
--- /dev/null
+++ b/autoload/fakepoll.h
@@ -0,0 +1,163 @@
+// fakepoll.h
+// poll using select
+// Warning: a call to this poll() takes about 4K of stack space.
+
+// Greg Parker gparker-web@sealiesoftware.com December 2000
+// This code is in the public domain and may be copied or modified without
+// permission.
+
+// Updated May 2002:
+// * fix crash when an fd is less than 0
+// * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
+// * don't set POLLIN or POLLOUT in revents if it wasn't requested
+// in events (only happens when an fd is in the poll set twice)
+
+#ifndef _FAKE_POLL_H
+#define _FAKE_POLL_H
+
+#include <limits.h>
+#ifndef FD_SETSIZE
+#define FD_SETSIZE OPEN_MAX
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef struct pollfd {
+ int fd; /* file desc to poll */
+ short events; /* events of interest on fd */
+ short revents; /* events that occurred on fd */
+} pollfd_t;
+
+
+/* poll flags */
+#define POLLIN 0x0001
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+
+/* synonyms */
+#define POLLNORM POLLIN
+#define POLLPRI POLLIN
+#define POLLRDNORM POLLIN
+#define POLLRDBAND POLLIN
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND POLLOUT
+
+/* ignored */
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
+{
+ struct timeval tv;
+ struct timeval *tvp;
+ fd_set readFDs, writeFDs, exceptFDs;
+ fd_set *readp, *writep, *exceptp;
+ struct pollfd *pollEnd, *p;
+ int selected;
+ int result;
+ int maxFD;
+
+ if (!pollSet) {
+ pollEnd = NULL;
+ readp = NULL;
+ writep = NULL;
+ exceptp = NULL;
+ maxFD = 0;
+ }
+ else {
+ pollEnd = pollSet + pollCount;
+ readp = &readFDs;
+ writep = &writeFDs;
+ exceptp = &exceptFDs;
+
+ FD_ZERO(readp);
+ FD_ZERO(writep);
+ FD_ZERO(exceptp);
+
+ // Find the biggest fd in the poll set
+ maxFD = 0;
+ for (p = pollSet; p < pollEnd; p++) {
+ if (p->fd > maxFD) maxFD = p->fd;
+ }
+
+ if (maxFD >= FD_SETSIZE) {
+ // At least one fd is too big
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Transcribe flags from the poll set to the fd sets
+ for (p = pollSet; p < pollEnd; p++) {
+ if (p->fd < 0) {
+ // Negative fd checks nothing and always reports zero
+ } else {
+ if (p->events & POLLIN) FD_SET(p->fd, readp);
+ if (p->events & POLLOUT) FD_SET(p->fd, writep);
+ if (p->events != 0) FD_SET(p->fd, exceptp);
+ // POLLERR is never set coming in; poll() always reports errors
+ // But don't report if we're not listening to anything at all.
+ }
+ }
+ }
+
+ // poll timeout is in milliseconds. Convert to struct timeval.
+ // poll timeout == -1 : wait forever : select timeout of NULL
+ // poll timeout == 0 : return immediately : select timeout of zero
+ if (pollTimeout >= 0) {
+ tv.tv_sec = pollTimeout / 1000;
+ tv.tv_usec = (pollTimeout % 1000) * 1000;
+ tvp = &tv;
+ } else {
+ tvp = NULL;
+ }
+
+
+ selected = select(maxFD+1, readp, writep, exceptp, tvp);
+
+
+ if (selected < 0) {
+ // Error during select
+ result = -1;
+ }
+ else if (selected > 0) {
+ // Select found something
+ // Transcribe result from fd sets to poll set.
+ // Also count the number of selected fds. poll returns the
+ // number of ready fds; select returns the number of bits set.
+ int polled = 0;
+ for (p = pollSet; p < pollEnd; p++) {
+ p->revents = 0;
+ if (p->fd < 0) {
+ // Negative fd always reports zero
+ } else {
+ if ((p->events & POLLIN) && FD_ISSET(p->fd, readp)) {
+ p->revents |= POLLIN;
+ }
+ if ((p->events & POLLOUT) && FD_ISSET(p->fd, writep)) {
+ p->revents |= POLLOUT;
+ }
+ if ((p->events != 0) && FD_ISSET(p->fd, exceptp)) {
+ p->revents |= POLLERR;
+ }
+
+ if (p->revents) polled++;
+ }
+ }
+ result = polled;
+ }
+ else {
+ // selected == 0, select timed out before anything happened
+ // Clear all result bits and return zero.
+ for (p = pollSet; p < pollEnd; p++) {
+ p->revents = 0;
+ }
+ result = 0;
+ }
+
+ return result;
+}
+
+
+#endif
diff --git a/autoload/proc.c b/autoload/proc.c
index 3042476..2adac11 100644
--- a/autoload/proc.c
+++ b/autoload/proc.c
@@ -12,7 +12,11 @@
#include <fcntl.h>
/* for poll() */
+#if defined __APPLE__
+#include "fakepoll.h"
+#else
#include <poll.h>
+#endif
/* for forkpty() */
#if defined __linux__
@@ -242,8 +246,14 @@ vp_file_read(char *args)
while (nr != 0) {
n = poll(&pfd, 1, timeout);
if (n == -1) {
+#if 0
return vp_stack_return_error(&_result, "poll() error: %s",
strerror(errno));
+#else
+ /* eof or error */
+ vp_stack_push_num(&_result, "%d", 1);
+ return vp_stack_return(&_result);
+#endif
} else if (n == 0) {
/* timeout */
break;
@@ -494,20 +504,23 @@ vp_pty_open(char *args)
strerror(errno));
} else if (pid == 0) {
/* child */
+ setsid();
+ ioctl(slave, TIOCSCTTY, 0);
+ close(master);
/* Create file descryptor. */
dup2(slave, 0); dup2(slave, 1); dup2(slave, 2);
close(slave);
if (execv(argv[0], argv) < 0) {
/* error */
- write(master, strerror(errno), strlen(strerror(errno)));
+ /* write(master, strerror(errno), strlen(strerror(errno))); */
_exit(EXIT_FAILURE);
}
} else {
/* parent */
- close(slave);
vp_stack_push_num(&_result, "%d", pid);
vp_stack_push_num(&_result, "%d", master);
- vp_stack_push_str(&_result, ttyname(master));
+ vp_stack_push_str(&_result, ttyname(slave));
+ close(slave);
return vp_stack_return(&_result);
}
/* DO NOT REACH HEAR */
diff --git a/autoload/proc.so b/autoload/proc.so
new file mode 100755
index 0000000..a495924
Binary files /dev/null and b/autoload/proc.so differ
diff --git a/make_mac.mak b/make_mac.mak
index e518012..a2515bf 100644
--- a/make_mac.mak
+++ b/make_mac.mak
@@ -2,7 +2,7 @@
TARGET=autoload/proc.so
SRC=autoload/proc.c
-CFLAGS=-W -Wall -Wno-unused -ansi -pedantic -bundle -fPIC -arch i386 -arch x86_64 -arch ppc -arch ppc64
+CFLAGS=-W -Wall -Wno-unused -bundle -fPIC -arch i386 -arch x86_64 -arch ppc -arch ppc64
LDFLAGS+=-lutil
all: $(TARGET)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment