summaryrefslogtreecommitdiff
path: root/Build/extra/djgpp/popen.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/extra/djgpp/popen.c')
-rw-r--r--Build/extra/djgpp/popen.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/Build/extra/djgpp/popen.c b/Build/extra/djgpp/popen.c
new file mode 100644
index 00000000000..67250d6ed7c
--- /dev/null
+++ b/Build/extra/djgpp/popen.c
@@ -0,0 +1,218 @@
+/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+/*
+ This is popen() and pclose() for MSDOS. They were developed using
+ Microsoft C, but should port easily to DOS C any compiler.
+
+ Original author: pacetti@fl-ngnet.army.mil
+
+ These routines are hacks, that is they SIMULATE thier UNIX
+ counterparts. Since MSDOS and won't allow concurrent process spawning,
+ you can't really pipe. I came up with this nearly stupid way around
+ piping because I wanted to have some portability between UNIX and MSDOS.
+ I'm probably not the first person to have this idea or implement it, but
+ I think I'm the first to give it away for free (no points?!).
+
+ The functions simulate popen() and pclose() by redirecting stdin or
+ stdout, then spawning a child processes via system().
+
+ If you popen() for read, the stdout is redirected to a temporary
+ file, and the child is spawned. The stdout is reopened via dup2(), the
+ temporary file is opened for read and a file pointer to it is returned.
+
+ If you popen() for write, a temporary file is opened for write, and
+ a file pointer to it is returned. When you pclose(), the stdin is
+ redirected to the temporary file and the child is spawned.
+
+ In both cases, pclose() closes and unlinks the temporary file.
+
+ A static linked list of C structures is built to store necessary
+ info for all popen()ed files so you can popen() more than one file at
+ a time.
+
+ The popen() function will return NULL on an error, or a valid FILE
+ *pointer on a successful open. The pclose() function will return
+ negative one (-1) on an error or zero (0) on a successful close.
+
+ The function prototypes are:
+
+ FILE *popen(command, mode)
+ char *command, char *mode;
+
+ int pclose(pp)
+ FILE *pp;
+
+ Where command is a character string equivilant to a MSDOS command
+ line, mode is "r" for read or "w" for write, and pp is a pointer to a
+ file opened through popen().
+
+ A main() function has been included for testing purposes, to compile
+ it define the preprocessor token TEST at compile time.
+ */
+
+#include <libc/stubs.h>
+#include <io.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libc/file.h>
+
+/* hold file pointer, descriptor, command, mode, temporary file name,
+ and the status of the command */
+struct pipe_list {
+ FILE *fp;
+ int fd;
+ int exit_status;
+ char *command, mode[10], temp_name[L_tmpnam];
+ struct pipe_list *next;
+};
+
+/* static, global list pointer */
+static struct pipe_list *pl = NULL;
+
+FILE *
+popen (const char *cm, const char *md) /* program name, pipe mode */
+{
+ struct pipe_list *l1, *l2;
+
+ /* make new node */
+ if ((l1 = (struct pipe_list *) malloc (sizeof (struct pipe_list))) == NULL)
+ return NULL;
+
+ /* zero out elements to we'll get here */
+ l1->fd = 0;
+ l1->fp = NULL;
+ l1->next = NULL;
+
+ /* if empty list - just grab new node */
+ if (!pl)
+ pl = l1;
+ else
+ {
+ /* otherwise, find last node in list */
+ ++(l1->fd);
+ l2 = pl;
+ while (l2->next)
+ {
+ ++(l1->fd);
+ l2 = l2->next;
+ };
+ /* add new node to list */
+ l2->next = l1;
+ }
+
+ /* stick in elements we know already */
+ l1->exit_status = -1;
+ strcpy (l1->mode, md);
+ if (tmpnam (l1->temp_name) == NULL)
+ return NULL;
+
+ /* if can save the program name, build temp file */
+ if ((l1->command = malloc(strlen(cm)+1)))
+ {
+ strcpy(l1->command, cm);
+ /* if caller wants to read */
+ if (l1->mode[0] == 'r')
+ {
+ /* dup stdout */
+ if ((l1->fd = dup (fileno (stdout))) == EOF)
+ l1->fp = NULL;
+ else if (!(l1->fp = freopen (l1->temp_name, "wb", stdout)))
+ l1->fp = NULL;
+ else
+ /* exec cmd */
+ if ((l1->exit_status = system (cm)) == EOF)
+ l1->fp = NULL;
+ /* reopen real stdout */
+ if (dup2 (l1->fd, fileno (stdout)) == EOF)
+ l1->fp = NULL;
+ /* if cmd couldn't be run, make sure we return NULL */
+ else if (l1->exit_status != EOF)
+ /* open file for reader */
+ l1->fp = fopen (l1->temp_name, l1->mode);
+ close(l1->fd);
+ }
+ else
+ /* if caller wants to write */
+ if (l1->mode[0] == 'w')
+ /* open temp file */
+ l1->fp = fopen (l1->temp_name, l1->mode);
+ else
+ /* unknown mode */
+ l1->fp = NULL;
+ }
+ return l1->fp; /* return == NULL ? ERROR : OK */
+}
+
+int
+pclose (FILE *pp)
+{
+ struct pipe_list *l1, *l2; /* list pointers */
+ int retval=0; /* function return value */
+
+ /* if pointer is first node */
+ if (pl->fp == pp)
+ {
+ /* save node and take it out the list */
+ l1 = pl;
+ pl = l1->next;
+ }
+ else
+ /* if more than one node in list */
+ if (pl->next)
+ {
+ /* find right node */
+ for (l2 = pl, l1 = pl->next; l1; l2 = l1, l1 = l2->next)
+ if (l1->fp == pp)
+ break;
+
+ /* take node out of list */
+ l2->next = l1->next;
+ }
+ else
+ return -1;
+
+ /* if FILE not in list - return error */
+ if (l1->fp == pp)
+ {
+ /* close the (hopefully) popen()ed file */
+ fclose (l1->fp);
+
+ /* if pipe was opened to write */
+ if (l1->mode[0] == 'w')
+ {
+ /* dup stdin */
+ if ((l1->fd = dup (fileno (stdin))) == EOF)
+ retval = -1;
+ else
+ /* open temp stdin */
+ if (!(l1->fp = freopen (l1->temp_name, "rb", stdin)))
+ retval = -1;
+ else
+ /* exec cmd */
+ if ((retval = system (l1->command)) != EOF)
+ {
+ /* reopen stdin */
+ if (dup2 (l1->fd, fileno (stdin)) == EOF)
+ retval = -1;
+ }
+ close(l1->fd);
+ }
+ else
+ /* if pipe was opened to read, return the exit status we saved */
+ if (l1->mode[0] == 'r')
+ retval = l1->exit_status;
+ else
+ /* invalid mode */
+ retval = -1;
+ }
+ remove (l1->temp_name); /* remove temporary file */
+ free (l1->command); /* dealloc memory */
+ free (l1); /* dealloc memory */
+ l1 = NULL; /* make pointer bogus */
+
+ return retval; /* retval==0 ? OK : ERROR */
+}