<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/fst/popen.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>’s /usr/web/sources/contrib/fst/popen.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
/*
* popen, pclose - open and close pipes (Plan 9 version)
*/
#include <u.h>
#include <libc.h>
enum { Stdin, Stdout, };
enum {
Rd,
Wr,
Maxfd = 200,
};
typedef struct {
long pid;
char *sts;
char stsset; /* flag: sts is valid */
} Pipe;
static Pipe pipes[Maxfd];
static int
_pipefd(int rfd, int wfd)
{
close(wfd);
return rfd;
}
int
popen(char *file, char *mode)
{
int pipedes[2];
long pid;
if (pipe(pipedes) < 0) /* cat's got the last pipe */
return -1;
if ((pid = fork()) < 0) { /* can't fork */
close(pipedes[Rd]);
close(pipedes[Wr]);
return -1;
}
/*
* The pipe was created and the fork succeeded.
* Now fiddle the file descriptors in both processes.
*/
if (pid == 0) { /* child process */
int sts;
/*
* If the mode is 'r', the child writes on stdout so the
* parent can read on its stdin from the child.
* If the mode is not 'r', the child reads on stdin so the
* parent can write on its stdout to the child.
*/
if (mode[0] == 'r') /* read from child */
sts = dup(pipedes[Wr], Stdout);
else /* write to child */
sts = dup(pipedes[Rd], Stdin);
if (sts < 0) /* couldn't fiddle fd's */
_exits("no pipe");
close(pipedes[Rd]);
close(pipedes[Wr]);
execl("/bin/rc", "rc", "-c", file, (char *)nil);
_exits("no /bin/rc"); /* no shell */
/* NOTREACHED */
return -1;
} else { /* parent process */
int fd;
/*
* If the mode is 'r', the parent reads on its stdin the child;
* otherwise the parent writes on its stdout to the child.
*/
if (mode[0] == 'r') /* read from child */
fd = _pipefd(pipedes[Rd], pipedes[Wr]);
else
fd = _pipefd(pipedes[Wr], pipedes[Rd]);
if (fd >= 0 && fd < Maxfd) {
Pipe *pp = pipes + fd;
pp->pid = pid; /* save fd's child's pid */
free(pp->sts);
pp->sts = nil;
pp->stsset = 0;
}
return fd;
}
}
static volatile int waiting;
static int
gotnote(void *, char *note)
{
if (strcmp(note, "interrupt") == 0)
if (waiting)
return 1; /* NCONT */
return 0; /* not a known note: NDFLT */
}
char *
pclose(int fd)
{
int pid; /* pid, wait status for some child */
Pipe *fpp, *app = nil, *spp;
static int registered;
if (fd < 0 || fd >= Maxfd)
return "fd out of range";
fpp = pipes + fd;
if (fpp->pid <= 0)
return "no child process for fd";
/*
* Ignore notes in case this process was catching them.
* Otherwise both this process and its child(ren) would
* catch these notes.
* Ideally I suppose popen should ignore the notes.
*/
if (!registered) {
atnotify(gotnote, 1);
registered = 1;
}
waiting = 1;
/*
* Wait for fd's child to die.
*/
close(fd);
while (!fpp->stsset) {
Waitmsg *wm = wait();
if (wm == nil)
break; /* ``can't happen'' */
pid = wm->pid;
/*
* ``Bring out your dead!''
* See if any fd is attached to this corpse;
* if so, give that fd its wait status.
*/
if (pid == fpp->pid) /* quick check */
app = fpp;
else
for (spp = pipes; spp < pipes + Maxfd; spp++)
if (pid == app->pid) {
app = spp;
break;
}
if (app != nil) {
/* record pid's status, possibly for later use */
free(app->sts);
app->sts = strdup(wm->msg);
app->stsset = 1;
}
}
waiting = 0;
return fpp->stsset? fpp->sts: "no open pipe";
}
/* Written by
[email protected] for Rangboom - fst 11/11/07 */
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="
http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="
http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="
http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:
[email protected]">
[email protected]</a>.</span>
</font></center>
</body>
</html>