home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file forms part of "TKERN" - "Troy's Kernel for Windows".
- *
- * Copyright (C) 1994 Troy Rollo <troy@cbme.unsw.EDU.AU>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <fcntl.h>
- #include <errno.h>
- #include <io.h>
- #include <sys/tfile.h>
- #include <errno.h>
- #include <memory.h>
- #include <malloc.h>
- #include <string.h>
-
- extern int nError;
- extern void tkern_wakeup_call(void);
-
- #define PIPESIZE 2048
- #define READER_CLOSED 1
- #define WRITER_CLOSED 2
- #define CLOSED (READER_CLOSED | WRITER_CLOSED)
-
- struct pipe_struc
- {
- int nReadSeq;
- int nWriteSeq;
- int iStart;
- int iEnd;
- int flags;
- struct pipe_struc *next;
- int iBuffer;
- char achBuffer[PIPESIZE + 1];
- };
-
- static struct pipe_struc *pipes = 0;
- static struct pipe_struc *lastpipe = 0;
- static int nSeq = 0;
-
-
- static void
- incseq(void)
- {
- nSeq = nSeq + 2;
- if (nSeq > 32000)
- nSeq = 0;
- }
-
- static void
- remove_pipe(int nSeq)
- {
- struct pipe_struc **link, *entry;
-
- for (link = &pipes; *link; link = &(*link)->next)
- {
- if ((*link)->nReadSeq == nSeq)
- {
- entry = *link;
- *link = entry->next;
- free(entry);
- return;
- }
- }
- }
-
- #pragma argsused
- int
- pipe_open( char const *pchFile,
- int nMode,
- int nAccess)
- {
- int nResult;
- struct pipe_struc *entry, **link;
-
- if (!strcmp(pchFile, "input"))
- {
- if (lastpipe)
- {
- remove_pipe(lastpipe->nReadSeq);
- lastpipe = 0;
- }
- link = &pipes;
- while (*link)
- {
- if ((*link)->nReadSeq == nSeq)
- {
- incseq();
- link = &pipes;
- }
- else
- {
- link = &(*link)->next;
- }
- }
- entry = (struct pipe_struc *) malloc(sizeof(struct pipe_struc));
- entry->nReadSeq = nSeq;
- entry->nWriteSeq = nSeq + 1;
- entry->next = 0;
- entry->iStart = 1;
- entry->iEnd = 0;
- entry->flags = 0;
- *link = entry;
- lastpipe = entry;
- incseq();
- nError = 0;
- return entry->nReadSeq;
- }
- else if (!strcmp(pchFile, "output"))
- {
- if (!lastpipe)
- {
- nError = EPIPE;
- return -1;
- }
- entry = lastpipe;
- lastpipe = 0;
- nError = 0;
- return entry->nWriteSeq;
- }
- else
- {
- nError = ENODEV;
- return -1;
- }
- }
-
- int
- pipe_close( int id)
- {
- struct pipe_struc *entry;
-
- for (entry = pipes; entry; entry = entry->next)
- {
- if (entry->nReadSeq == id)
- {
- entry->flags |= READER_CLOSED;
- if ((entry->flags & CLOSED) == CLOSED)
- remove_pipe(entry->nReadSeq);
- return 0;
- }
- if (entry->nWriteSeq == id)
- {
- entry->flags |= WRITER_CLOSED;
- if ((entry->flags & CLOSED) == CLOSED)
- remove_pipe(entry->nReadSeq);
- return 0;
- }
- }
- nError = EFAULT;
- return -1;
- }
-
- int
- pipe_read( int id,
- char *pchData,
- int nBytes)
- {
- int nAvailable;
- struct pipe_struc *entry;
- int nTotal = 0;
-
- if (id & 1) /* Indicates a write-side */
- {
- nError = EACCES;
- return -1;
- }
- for (entry = pipes; entry; entry = entry->next)
- {
- if (entry->nReadSeq == id)
- break;
- }
- if (!entry)
- {
- nError = EFAULT;
- return -1;
- }
- nAvailable = entry->iEnd - entry->iStart;
- if (nAvailable < 0)
- nAvailable += PIPESIZE + 1;
- if (!nAvailable)
- {
- if (entry->flags & WRITER_CLOSED)
- {
- return 0;
- }
- else
- {
- return FR_NOTREADY;
- }
- }
- if (nAvailable < nBytes)
- nBytes = nAvailable;
- if (nBytes + entry->iStart > PIPESIZE)
- {
- nTotal = PIPESIZE - entry->iStart + 1;
- memcpy(pchData,
- entry->achBuffer + entry->iStart,
- nTotal);
- nBytes -= nTotal;
- pchData += nTotal;
- entry->iStart = 0;
- }
- memcpy(pchData, entry->achBuffer + entry->iStart, nBytes);
- entry->iStart += nBytes;
- nTotal += nBytes;
- tkern_wakeup_call();
- return nTotal;
- }
-
- int
- pipe_write( int id,
- char const *pchData,
- int nBytes)
- {
- struct pipe_struc *entry;
- int nTotal = 0;
- int nAvailable;
-
- if (!(id & 1)) /* Indicates a read-side */
- {
- nError = EACCES;
- return -1;
- }
- for (entry = pipes; entry; entry = entry->next)
- {
- if (entry->nWriteSeq == id)
- break;
- }
- if (!entry)
- {
- nError = EFAULT;
- return -1;
- }
- if (entry->flags & READER_CLOSED)
- {
- /* Write on a pipe with nobody to read */
- nError = EPIPE;
- return -1;
- }
- nAvailable = entry->iStart - entry->iEnd - 1;
- if (nAvailable < 0)
- nAvailable = nAvailable + PIPESIZE + 1;
- if (nAvailable < nBytes)
- nBytes = nAvailable;
- if (!nAvailable)
- {
- return FR_NOTREADY;
- }
- if (nBytes + entry->iEnd > PIPESIZE)
- {
- nTotal = PIPESIZE - entry->iEnd + 1;
- memcpy(entry->achBuffer + entry->iEnd,
- pchData,
- nTotal);
- nBytes -= nTotal;
- pchData += nTotal;
- entry->iEnd = 0;
- }
- memcpy(entry->achBuffer + entry->iEnd, pchData, nBytes);
- entry->iEnd += nBytes;
- nTotal += nBytes;
- tkern_wakeup_call();
- return nTotal;
- }
-
- int
- pipe_ioctl(void)
- {
- nError = EINVAL;
- return -1;
- }
-
-