LispObj * Lisp_Listen(LispBuiltin *builtin) /* listen &optional input-stream */ { LispFile *file = NULL; LispObj *result = NIL; LispObj *stream; stream = ARGUMENT(0); if (stream == UNSPEC) stream = NIL; else if (stream != NIL) { CHECK_STREAM(stream); } else stream = lisp__data.standard_input; if (stream->data.stream.readable) { switch (stream->data.stream.type) { case LispStreamString: if (SSTREAMP(stream)->input < SSTREAMP(stream)->length) result = T; break; case LispStreamFile: file = FSTREAMP(stream); break; case LispStreamStandard: file = FSTREAMP(stream); break; case LispStreamPipe: file = IPSTREAMP(stream); break; } if (file != NULL) { if (file->available || file->offset < file->length) result = T; else { unsigned char c; if (!file->nonblock) { if (fcntl(file->descriptor, F_SETFL, O_NONBLOCK) < 0) LispDestroy("%s: fcntl: %s", STRFUN(builtin), strerror(errno)); file->nonblock = 1; } if (read(file->descriptor, &c, 1) == 1) { LispFungetc(file, c); result = T; } } } } return (result); }
LispObj * Lisp_Close(LispBuiltin *builtin) /* close stream &key abort */ { LispObj *stream, *oabort; oabort = ARGUMENT(1); stream = ARGUMENT(0); CHECK_STREAM(stream); if (stream->data.stream.readable || stream->data.stream.writable) { stream->data.stream.readable = stream->data.stream.writable = 0; if (stream->data.stream.type == LispStreamFile) { LispFclose(stream->data.stream.source.file); stream->data.stream.source.file = NULL; } else if (stream->data.stream.type == LispStreamPipe) { if (IPSTREAMP(stream)) { LispFclose(IPSTREAMP(stream)); IPSTREAMP(stream) = NULL; } if (OPSTREAMP(stream)) { LispFclose(OPSTREAMP(stream)); OPSTREAMP(stream) = NULL; } if (EPSTREAMP(stream)) { LispFclose(EPSTREAMP(stream)); EPSTREAMP(stream) = NULL; } if (PIDPSTREAMP(stream) > 0) { kill(PIDPSTREAMP(stream), oabort == UNSPEC || oabort == NIL ? SIGTERM : SIGKILL); waitpid(PIDPSTREAMP(stream), NULL, 0); } } return (T); } return (NIL); }
/* Helper function, primarily for use with the xt module */ LispObj * Lisp_PipeInputDescriptor(LispBuiltin *builtin) /* pipe-input-descriptor pipe-stream */ { LispObj *pipe_stream; pipe_stream = ARGUMENT(0); if (!STREAMP(pipe_stream) || pipe_stream->data.stream.type != LispStreamPipe) LispDestroy("%s: %s is not a pipe stream", STRFUN(builtin), STROBJ(pipe_stream)); if (!IPSTREAMP(pipe_stream)) LispDestroy("%s: pipe %s is unreadable", STRFUN(builtin), STROBJ(pipe_stream)); return (INTEGER(LispFileno(IPSTREAMP(pipe_stream)))); }
/* * Implementation */ int LispGet(void) { int ch = EOF; LispUngetInfo *unget = lisp__data.unget[lisp__data.iunget]; if (unget->offset) ch = ((unsigned char*)unget->buffer)[--unget->offset]; else if (SINPUT->data.stream.readable) { LispFile *file = NULL; switch (SINPUT->data.stream.type) { case LispStreamStandard: case LispStreamFile: file = FSTREAMP(SINPUT); break; case LispStreamPipe: file = IPSTREAMP(SINPUT); break; case LispStreamString: ch = LispSgetc(SSTREAMP(SINPUT)); break; default: ch = EOF; break; } if (file != NULL) { if (file->nonblock) { if (fcntl(file->descriptor, F_SETFL, 0) < 0) LispDestroy("fcntl: %s", strerror(errno)); file->nonblock = 0; } ch = LispFgetc(file); } } else LispDestroy("cannot read from *STANDARD-INPUT*"); if (ch == EOF) lisp__data.eof = 1; return (ch); }