Created
July 7, 2009 13:47
-
-
Save splhack/142081 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 [email protected] 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