home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Lisp.m
- ** Lisp client object with message-based I/O.
- ** Lee Boynton, NeXT, Inc., 1989
- */
-
- #import <mach.h>
- #import <stdlib.h>
- #import <string.h>
- #import <fcntl.h>
- #import <signal.h>
- #import <sys/wait.h>
- #import <dpsclient/dpsclient.h>
- #import <defaults/defaults.h>
- #import <appkit/Application.h>
- #import <objc/List.h>
- #import "Lisp.h"
-
- @implementation Lisp
-
- #define READ_BUF_SIZE (8191)
- static char read_buf[READ_BUF_SIZE+1];
-
- static void *read_lisp(int fd, Lisp *self)
- {
- extern int read();
- NXEvent event;
- int count = read(fd,read_buf,READ_BUF_SIZE);
- id delegate = self->delegate;
- BOOL tellDelegate = NO;
- if (delegate && [delegate respondsTo:@selector(lispOutput:)])
- tellDelegate = YES;
- while (count > 0) {
- read_buf[count] = '\0';
- if (tellDelegate)
- [delegate lispOutput:(const char *)read_buf];
- if ([NXApp peekNextEvent:-1 into:&event waitFor:0.0 threshold:1])
- break;
- count = read(fd,read_buf,READ_BUF_SIZE);
- }
- }
-
- static int launch(const char *name, const char **argv,
- int *child_pid,
- int *write_child_fd, int *read_child_fd)
- {
- extern int pipe();
- extern int fork();
- extern int dup2();
- extern int close();
- extern int execvp();
- extern int fcntl();
- extern int close();
- int err, pid;
- int p_to_child[2], p_from_child[2];
-
- if ((err = pipe(p_to_child)) < 0)
- return err;
- if ((err = pipe(p_from_child)) < 0) {
- close(p_to_child[0]);
- close(p_to_child[1]);
- return err;
- }
- if ((pid = fork()) == 0) {
- dup2(p_to_child[0], 0);
- dup2(p_from_child[1], 1);
- dup2(p_from_child[1], 2);
- close(p_to_child[1]);
- close(p_from_child[0]);
- execvp(name, argv);
- exit(127);
- }
- if (pid == -1) {
- close(p_to_child[0]);
- close(p_to_child[1]);
- close(p_from_child[0]);
- close(p_from_child[1]);
- return -1;
- }
- *child_pid = pid;
- *write_child_fd = p_to_child[1];
- close(p_to_child[0]);
- *read_child_fd = p_from_child[0];
- close(p_from_child[1]);
- return fcntl(*read_child_fd,F_SETFL,FNDELAY);
- }
-
-
- static id lispList = nil;
-
- static id findLispForPid(int pid) {
- Lisp *self;
- int i, max = [lispList count];
- for (i=0; i<max; i++) {
- self = (Lisp *)[lispList objectAt:i];
- if (self->lisp_pid == pid)
- return self;
- }
- return nil;
- }
-
- static void lispDied(int ignore) {
- union wait epitaph;
- int pid;
- Lisp *self;
-
- while (1) {
- pid = wait3(&epitaph,WNOHANG,0);
- if (pid > 0) {
- if (self = findLispForPid(pid)) {
- self->lisp_pid = 0;
- break;
- }
- } else
- break;
- }
- signal(SIGCHLD,&lispDied);
- }
-
- + initialize
- {
- if (!lispList)
- lispList = [List new];
- signal(SIGCHLD,&lispDied);
- return self;
- }
-
- + new
- {
- int err;
- const char *argv[2];
- const char *imageName = NXGetDefaultValue([NXApp appName],"LispImage");
- self = [super new];
- argv[0] = imageName;
- argv[1] = NULL;
- [lispList addObject:self];
- err = launch(imageName,argv,&lisp_pid, &lisp_in_fd,&lisp_out_fd);
- if (err) {
- [self free];
- return nil;
- }
- DPSAddFD(lisp_out_fd,(DPSFDProc)read_lisp,(void *)self,1);
- return self;
- }
-
- - free
- {
- extern int kill();
- DPSRemoveFD(lisp_out_fd);
- [lispList removeObject:self];
- if (lisp_pid)
- kill(lisp_pid,9);
- return [super free];
- }
-
- - setDelegate:anObject
- {
- delegate = anObject;
- return self;
- }
-
- - delegate
- {
- return delegate;
- }
-
- - inputLisp:(const char *)theString
- {
- extern int write();
- int i, count = strlen(theString);
- if (!lisp_pid || (count != write(lisp_in_fd,theString,count)))
- return nil;
- return self;
- }
-
- - interruptLisp
- {
- extern int kill();
- if (lisp_pid && kill(lisp_pid,2))
- return nil;
- return self;
- }
-
- @end
-
-
-
-
-
-
-
-
-
-