home *** CD-ROM | disk | FTP | other *** search
- /* stream commands for tcl */
- #include <stdio.h>
- #include <tcl.h>
- #include <errno.h>
- #include <ctype.h>
- #include "handler.h"
- #include "stream.h"
-
- #define STATIC
-
- int streamOpen(),
- streamClose(),
- streamGets(),
- streamPuts(),
- streamEof(),
- streamName(),
- streamErr(),
- streamTell(),
- streamList();
- streamSeek();
-
- static struct subcmd commands[] = {
- { streamOpen, "open", 2, 2, "name mode" },
- { streamClose, "close", 1, 1, "handle" },
- { streamGets, "gets", 1, 2, "handle [var]" },
- { streamPuts, "puts", 2, 2, "handle line" },
- { streamEof, "eof", 1, 1, "handle" },
- { streamErr, "error", 1, 1, "handle" },
- { streamName, "name", 1, 1, "handle" },
- { streamTell, "tell", 1, 1, "handle" },
- { streamList, "list", 0, 0, "" },
- { streamSeek, "seek", 2, 3, "handle offset [whence]" },
- };
-
- save_err(s)
- struct stream *s;
- {
- char *strerror();
- extern int errno;
- char *name;
-
- name = strerror(errno);
- if(!name)
- return;
-
- if(s->error) ckfree(s->error);
- s->error = 0;
- s->error = ckalloc(strlen(name)+1);
- strcpy(s->error, name);
- }
-
- static struct {
- char *name;
- int len;
- int type;
- } types[] = {
- { "file", 4, ST_FILE },
- { "pipe", 4, ST_PIPE }
- };
- int ntypes = sizeof types / sizeof *types;
-
- STATIC int get_id(streams, name)
- struct streams *streams;
- char *name;
- {
- int id;
- int t;
-
- for(t = 0; t < ntypes; t++)
- if(strncmp(name, types[t].name, types[t].len) == 0)
- break;
- if(t >= ntypes)
- return -1;
- name+=types[t].len;
- if(!isdigit(*name))
- return -1;
- id = atoi(name);
- if(streams->s[id] && streams->s[id]->type == types[t].type)
- return id;
- return -1;
- }
-
- STATIC char *get_name(streams, id)
- struct streams *streams;
- int id;
- {
- static char name[32];
- int t;
-
- if(id < 0)
- return 0;
-
- for(t = 0; t < ntypes; t++)
- if(streams->s[id]->type == types[t].type)
- break;
- if(t >= ntypes)
- return 0;
-
- sprintf(name, "%s%d", types[t].name, id);
-
- return name;
- }
-
- STATIC struct stream *get_stream(streams, name)
- struct streams *streams;
- char *name;
- {
- int id;
- struct stream *s;
-
- id = get_id(streams, name);
- if(id >= 0)
- return streams->s[id];
- else
- return 0;
- }
-
- STATIC struct stream *add_stream(streams, filename, fp)
- struct streams *streams;
- char *filename;
- FILE *fp;
- {
- int id;
- struct stream *s;
-
- for(id = 0; id < streams->n; id++)
- if(!streams->s[id])
- break;
- if(id >= MAXSTREAMS) {
- extern int errno;
-
- errno = ENOMEM;
- return 0;
- }
- if(id >= streams->n)
- streams->n++;
-
- s = (struct stream *)ckalloc(sizeof(struct stream)
- + (filename ? (strlen(filename)+1) : 0) );
-
- if(filename) {
- s->filename = (char *)(s+1);
- strcpy(s->filename, filename);
- } else
- s->filename = NULL;
- s->id = id;
- s->fp = fp;
- s->error = NULL;
- streams->s[id] = s;
-
- return s;
- }
-
- STATIC del_stream(streams, id)
- struct streams *streams;
- int id;
- {
- struct stream *s;
-
- if(s = streams->s[id]) {
- streams->s[id] = 0;
- if(s->error) ckfree(s->error);
- ckfree(s);
- return 1;
- }
- return 0;
- }
-
- stream_term(stab)
- struct cmd_table *stab;
- {
- int id;
- struct streams *streams = (struct streams *)stab->data;
-
- for(id = 0; id < streams->n; id++)
- if(streams->s[id])
- del_stream(streams, id);
- ckfree(streams);
- ckfree(stab);
- }
-
- stream_init(interp)
- Tcl_Interp *interp;
- {
- struct cmd_table *streamTable;
- struct streams *streamHead;
-
- streamTable = (struct cmd_table *) ckalloc(sizeof *streamTable);
- streamHead = (struct streams *) ckalloc(sizeof (struct streams));
- streamHead->n = 0;
-
- streamTable->name = "stream";
- streamTable->data = (ClientData) streamHead;
- streamTable->cmdc = sizeof(commands) / sizeof(*commands);
- streamTable->cmdv = commands;
-
- Tcl_CreateCommand(interp, "stream",
- cmdHandler, (ClientData) streamTable, stream_term);
- add_stream(streamTable->data, (char *)NULL, stdin);
- add_stream(streamTable->data, (char *)NULL, stdout);
- add_stream(streamTable->data, (char *)NULL, stderr);
- }
-
- STATIC int streamOpen(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- FILE *fp;
- struct stream *s;
- int type;
- char *ptr, *strchr();
-
- if(ptr = strchr(argv[1], 'p')) {
- do
- ptr[0] = ptr[1];
- while(*ptr++);
- fp = popen(argv[0], argv[1]);
- type = ST_PIPE;
- } else {
- fp = fopen(argv[0], argv[1]);
- type = ST_FILE;
- }
-
- if(!fp) {
- char *strerror();
- extern int errno;
- char *s = strerror(errno);
- if(s)
- sprintf(interp->result, "%s: %s", argv[0], s);
- else
- Tcl_Return(interp, (char *)NULL, TCL_STATIC);
- return TCL_ERROR;
- }
-
- s = add_stream(streams, argv[0], fp);
- s->type = type;
- if(s) {
- if(s->id < 0)
- Tcl_Return(interp, (char *)NULL, TCL_STATIC);
- else
- Tcl_Return(interp, get_name(streams, s->id), TCL_VOLATILE);
- return TCL_OK;
- } else {
- sprintf(interp->result, "%s: Too many open streams", argv[0]);
- return TCL_ERROR;
- }
- }
-
- STATIC not_open(interp, name)
- Tcl_Interp *interp;
- char *name;
- {
- sprintf(interp->result,
- "%.50s is not an open stream", name);
- }
-
- STATIC int streamClose(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
-
- if(!s) {
- not_open(interp, handle);
- return TCL_ERROR;
- }
-
- if(s->type==ST_PIPE)
- pclose(s->fp);
- else if(s->type==ST_FILE)
- fclose(s->fp);
-
- del_stream(streams, s->id);
- return TCL_OK;
- }
-
- STATIC int streamGets(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
- char *buffer = ckalloc(BUFSIZ);
- char *ptr, *strchr();
- int len;
-
- if(!s) {
- not_open(interp, handle);
- ckfree(buffer);
- return TCL_ERROR;
- }
-
- if(fgets(buffer, BUFSIZ, s->fp)) {
- len = strlen(buffer);
- ptr = strchr(buffer, '\n');
- if(ptr)
- *ptr = 0;
- if(argc==1) {
- sprintf(interp->result, "%d", len);
- Tcl_SetVar(interp, argv[0], buffer, 0);
- } else
- Tcl_Return(interp, buffer, TCL_VOLATILE);
- }
- else
- {
- if(argc==1)
- Tcl_Return(interp, "0", TCL_STATIC);
- else
- Tcl_Return(interp, (char *)NULL, TCL_STATIC);
- }
- ckfree(buffer);
- return TCL_OK;
- }
-
- STATIC int streamPuts(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
- char buffer[BUFSIZ];
-
- if(!s) {
- not_open(interp, handle);
- return TCL_ERROR;
- }
-
- if(fputs(argv[0], s->fp) == EOF) save_err(s);
- if(putc('\n', s->fp) == EOF) save_err(s);
-
- return TCL_OK;
- }
-
- STATIC int streamTell(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
- long offset, ftell();
-
- if(!s) {
- not_open(interp, handle);
- return TCL_ERROR;
- }
-
- sprintf(interp->result, "%ld", offset = ftell(s->fp));
- if(offset == -1) save_err(s);
- return TCL_OK;
- }
-
- STATIC int streamEof(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
-
- if(!s) {
- not_open(interp, handle);
- return TCL_ERROR;
- }
-
- sprintf(interp->result, "%d", !!feof(s->fp));
- return TCL_OK;
- }
-
- STATIC int streamErr(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
-
- if(!s) {
- not_open(interp, handle);
- return TCL_ERROR;
- }
-
- if(ferror(s->fp) && s->error)
- Tcl_Return(interp, s->error, TCL_VOLATILE);
- else
- Tcl_Return(interp, (char *)NULL, TCL_STATIC);
-
- return TCL_OK;
- }
-
- STATIC int streamName(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
-
- if(!s) {
- not_open(interp, handle);
- return TCL_ERROR;
- }
-
- if(s->filename)
- Tcl_Return(interp, s->filename, TCL_VOLATILE);
- else
- Tcl_Return(interp, (char *)NULL, TCL_STATIC);
-
- return TCL_OK;
- }
-
- STATIC int streamSeek(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char *handle = (--argc, *argv++);
- struct stream *s = get_stream(streams, handle);
- int whence, ret, fseek();
- long offset, fftell();
- long strtol();
- char *endptr;
-
- if(!s) {
- not_open(interp, handle);
- return TCL_ERROR;
- }
-
- if(argc > 1) whence = atoi(argv[1]);
- else whence = 0;
-
- offset = strtol(argv[0], &endptr, 0);
-
- ret = fseek(s->fp, offset, whence);
- if(ret==0) offset = ftell(s->fp);
- else offset = -1;
- sprintf(interp->result, "%ld", offset);
- if(offset == -1) save_err(s);
-
- return TCL_OK;
- }
-
- STATIC int streamList(interp, streams, argc, argv)
- Tcl_Interp *interp;
- struct streams *streams;
- int argc;
- char **argv;
- {
- char buffer[BUFSIZ];
- int id;
- struct stream *s;
- char *p;
-
- p = 0;
- for(id = 0; id < streams->n; id++) {
- if(s = streams->s[id]) {
- if(!p)
- p = buffer;
- else
- *p++ = ' ';
- if(s->filename) {
- char *strchr();
- if(strchr(s->filename, ' ') == NULL)
- sprintf(p, "{%s %s}",
- get_name(streams, id),
- s->filename);
- else
- sprintf(p, "{%s {%s}}",
- get_name(streams, id),
- s->filename);
- } else
- sprintf(p, "%s", get_name(streams, id));
- p += strlen(p);
- }
- }
- Tcl_Return(interp, buffer, TCL_VOLATILE);
- return TCL_OK;
- }
-