home *** CD-ROM | disk | FTP | other *** search
- /* popen(): open a file handle to a process. Works only under MiNT.
- * Written by Eric R. Smith, based on the TOS version by Kai-Uwe Bloem.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <process.h>
- #include <fcntl.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
-
- __EXTERN int wait __PROTO((int *));
-
- struct _pipe {
- int pid; /* process id of child */
- FILE *pfile; /* created file descriptor */
- struct _pipe *pnext; /* next pipe in the list. */
- };
-
- static struct _pipe *__pipes = NULL; /* head of pipe list */
-
- FILE *popen(command, type)
- const char *command, *type;
- {
- struct _pipe *p; /* the new pipe's list entry */
- int pipfd[2]; /* pipe file handles */
- int savefd; /* saved file descriptor for parent */
- int kidfd; /* file descriptor changed in child */
- /* 1 for "r", 0 for "w" */
-
- char *shell;
- FILE *pipefile = 0;
- extern int __mint;
-
- if (__mint == 0) {
- errno = EINVAL;
- return (FILE *)0;
- }
-
- shell = getenv("SHELL");
- if (!shell)
- shell = "sh";
-
- /* get space for the new pipe. If we can't get it then that's that */
- p = (struct _pipe *) malloc(sizeof(struct _pipe));
- if (p == NULL) return (FILE *)0;
-
- /* initialize the new pipe entry */
- kidfd = (*type == 'r') ? 1 : 0;
-
- savefd = dup(kidfd);
-
- if (savefd < 0 || pipe(pipfd) != 0) { /* can't create pipe?? */
- free(p);
- return (FILE *)0;
- }
-
- dup2(pipfd[kidfd], kidfd);
- close(pipfd[kidfd]);
- p->pid = spawnlp(P_NOWAIT, shell, shell, "-c", command, (char *)0);
- dup2(savefd, kidfd);
- close(savefd);
-
- if (p->pid > 0) { /* command ran all right */
- /* note: 1-kidfd tells us which handle to use in the parent */
- pipefile = fdopen(pipfd[1 - kidfd], type);
- }
-
- if (pipefile) {
- p->pfile = pipefile;
- p->pnext = __pipes;
- __pipes = p;
- }
- else {
- free(p);
- }
- return pipefile;
- }
-
- /* close a pipe created by popen().
- */
- int pclose(fp)
- FILE *fp;
- {
- struct _pipe *p, /* the pipe's list element */
- *q; /* predecessor of p in the list */
- int status = -1; /* return status of the command */
- int pid;
-
- /* search the pipe list for a pipe matching the FILE descriptor */
- for (p = __pipes, q = NULL; p && p->pfile != fp; q = p, p = p->pnext);
- if (p == NULL) /* Never had a popen() for this file... */
- return status; /* this pclose call makes no sense ! */
-
- fclose(p->pfile); /* close the connection */
-
- /* now wait for the command to finish */
-
- do {
- pid = wait(&status);
- } while (pid >= 0 && pid != p->pid);
-
- /* remove the pipe from the list */
- if (q) /* not the first in the list, unlink it from previous pipe */
- q->pnext = p->pnext;
- else /* first in the list, set new list head */
- __pipes = __pipes->pnext;
-
- /* Now free the pipe entry */
- free(p);
-
- return status;
- }
-