OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [newlib-1.18.0/] [newlib/] [libc/] [posix/] [popen.c] - Blame information for rev 207

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
/*      $NetBSD: popen.c,v 1.11 1995/06/16 07:05:33 jtc Exp $   */
2
 
3
/*
4
 * Copyright (c) 1988, 1993, 2006
5
 *      The Regents of the University of California.  All rights reserved.
6
 *
7
 * This code is derived from software written by Ken Arnold and
8
 * published in UNIX Review, Vol. 6, No. 8.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 4. Neither the name of the University nor the names of its contributors
19
 *    may be used to endorse or promote products derived from this software
20
 *    without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 */
34
 
35
/*
36
FUNCTION
37
<<popen>>, <<pclose>>---tie a stream to a command string
38
 
39
INDEX
40
        popen
41
INDEX
42
        pclose
43
 
44
ANSI_SYNOPSIS
45
        #include <stdio.h>
46
        FILE *popen(const char *<[s]>, const char *<[mode]>);
47
 
48
        int pclose(FILE *<[f]>);
49
 
50
DESCRIPTION
51
Use <<popen>> to create a stream to a child process executing a
52
command string <<*<[s]>>> as processed by <</bin/sh>> on your system.
53
The argument <[mode]> must start with either `<<r>>', where the stream
54
reads from the child's <<stdout>>, or `<<w>>', where the stream writes
55
to the child's <<stdin>>.  As an extension, <[mode]> may also contain
56
`<<e>>' to set the close-on-exec bit of the parent's file descriptor.
57
The stream created by <<popen>> must be closed by <<pclose>> to avoid
58
resource leaks.
59
 
60
Streams created by prior calls to <<popen>> are not visible in
61
subsequent <<popen>> children, regardless of the close-on-exec bit.
62
 
63
Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
64
available.
65
 
66
RETURNS
67
<<popen>> returns a file stream opened with the specified <[mode]>,
68
or <<NULL>> if a child process could not be created.  <<pclose>>
69
returns -1 if the stream was not created by <<popen>> or if the
70
application used <<wait>> or similar to steal the status; otherwise
71
it returns the exit status of the child which can be interpreted
72
in the same manner as a status obtained by <<waitpid>>.
73
 
74
PORTABILITY
75
POSIX.2 requires <<popen>> and <<pclose>>, but only specifies a mode
76
of just <<r>> or <<w>>.  Where <<sh>> is found is left unspecified.
77
 
78
Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
79
<<_wait_r>>, <<pipe>>, <<fcntl>>, <<sbrk>>.
80
*/
81
 
82
#ifndef _NO_POPEN
83
 
84
#if defined(LIBC_SCCS) && !defined(lint)
85
#if 0
86
static char sccsid[] = "@(#)popen.c     8.1 (Berkeley) 6/4/93";
87
#else
88
static char rcsid[] = "$NetBSD: popen.c,v 1.11 1995/06/16 07:05:33 jtc Exp $";
89
#endif
90
#endif /* LIBC_SCCS and not lint */
91
 
92
#include <sys/param.h>
93
#include <sys/types.h>
94
#include <sys/wait.h>
95
 
96
#include <signal.h>
97
#include <errno.h>
98
#include <unistd.h>
99
#include <stdio.h>
100
#include <stdlib.h>
101
#include <string.h>
102
#include <paths.h>
103
#include <fcntl.h>
104
 
105
static struct pid {
106
        struct pid *next;
107
        FILE *fp;
108
        pid_t pid;
109
} *pidlist;
110
 
111
FILE *
112
_DEFUN(popen, (program, type),
113
        const char *program _AND
114
        const char *type)
115
{
116
        struct pid *cur, *last;
117
        FILE *iop;
118
        int pdes[2], pid;
119
 
120
       if ((*type != 'r' && *type != 'w')
121
           || (type[1]
122
#ifdef HAVE_FCNTL
123
               && (type[2] || (type[1] != 'e'))
124
#endif
125
                               )) {
126
                errno = EINVAL;
127
                return (NULL);
128
        }
129
 
130
        if ((cur = malloc(sizeof(struct pid))) == NULL)
131
                return (NULL);
132
 
133
        if (pipe(pdes) < 0) {
134
                free(cur);
135
                return (NULL);
136
        }
137
 
138
        switch (pid = vfork()) {
139
        case -1:                        /* Error. */
140
                (void)close(pdes[0]);
141
                (void)close(pdes[1]);
142
                free(cur);
143
                return (NULL);
144
                /* NOTREACHED */
145
        case 0:                          /* Child. */
146
                if (*type == 'r') {
147
                        if (pdes[1] != STDOUT_FILENO) {
148
                                (void)dup2(pdes[1], STDOUT_FILENO);
149
                                (void)close(pdes[1]);
150
                        }
151
                        if (pdes[0] != STDOUT_FILENO) {
152
                                (void) close(pdes[0]);
153
                        }
154
                } else {
155
                        if (pdes[0] != STDIN_FILENO) {
156
                                (void)dup2(pdes[0], STDIN_FILENO);
157
                                (void)close(pdes[0]);
158
                        }
159
                        (void)close(pdes[1]);
160
                }
161
                /* Close all fd's created by prior popen.  */
162
                for (last = NULL, cur = pidlist; cur;
163
                     last = cur, cur = cur->next)
164
                        (void)close (fileno (cur->fp));
165
                execl(_PATH_BSHELL, "sh", "-c", program, NULL);
166
                _exit(127);
167
                /* NOTREACHED */
168
        }
169
 
170
        /* Parent; assume fdopen can't fail. */
171
        if (*type == 'r') {
172
                iop = fdopen(pdes[0], type);
173
                (void)close(pdes[1]);
174
        } else {
175
                iop = fdopen(pdes[1], type);
176
                (void)close(pdes[0]);
177
        }
178
 
179
#ifdef HAVE_FCNTL
180
        /* Mark pipe cloexec if requested.  */
181
        if (type[1] == 'e')
182
                fcntl (fileno (iop), F_SETFD,
183
                       fcntl (fileno (iop), F_GETFD, 0) | FD_CLOEXEC);
184
#endif /* HAVE_FCNTL */
185
 
186
        /* Link into list of file descriptors. */
187
        cur->fp = iop;
188
        cur->pid =  pid;
189
        cur->next = pidlist;
190
        pidlist = cur;
191
 
192
        return (iop);
193
}
194
 
195
/*
196
 * pclose --
197
 *      Pclose returns -1 if stream is not associated with a `popened' command,
198
 *      if already `pclosed', or waitpid returns an error.
199
 */
200
int
201
_DEFUN(pclose, (iop),
202
        FILE *iop)
203
{
204
        register struct pid *cur, *last;
205
        int pstat;
206
        pid_t pid;
207
 
208
        (void)fclose(iop);
209
 
210
        /* Find the appropriate file pointer. */
211
        for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
212
                if (cur->fp == iop)
213
                        break;
214
        if (cur == NULL)
215
                return (-1);
216
 
217
        do {
218
                pid = waitpid(cur->pid, &pstat, 0);
219
        } while (pid == -1 && errno == EINTR);
220
 
221
        /* Remove the entry from the linked list. */
222
        if (last == NULL)
223
                pidlist = cur->next;
224
        else
225
                last->next = cur->next;
226
        free(cur);
227
 
228
        return (pid == -1 ? -1 : pstat);
229
}
230
 
231
#endif  /* !_NO_POPEN  */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.