2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: sfpopen.c /main/3 1995/11/01 18:33:06 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
31 * Copyright (c) 1995 AT&T Corp. *
32 * All Rights Reserved *
34 * This software is licensed by AT&T Corp. *
35 * under the terms and conditions of the license in *
36 * http://www.research.att.com/orgs/ssr/book/reuse *
38 * This software was created by the *
39 * Software Engineering Research Department *
40 * AT&T Bell Laboratories *
42 * For further information contact *
43 * gsf@research.att.com *
45 ***************************************************************/
60 #include <sys/vfork.h>
65 typedef void(*Handler_t)_ARG_((int));
66 #define EXIT_NOTFOUND 127
69 extern int fork _ARG_((void));
70 extern int waitpid _ARG_((int, int*, int));
71 extern int wait _ARG_((int*));
72 extern int pipe _ARG_((int*));
73 extern int execl _ARG_((char*,char*,...));
80 #endif /*_PACKAGE_ast*/
83 Sfio_t *sfpopen(Sfio_t* f, const char* command, const char* mode)
85 Sfio_t *sfpopen(f,command,mode)
87 char *command; /* command to execute */
88 char *mode; /* mode of the stream */
94 reg long flags = PROC_IGNORE;
97 if (!command || !command[0] || !(sflags = _sftype(mode, NiL)))
101 if (sflags & SF_WRITE)
105 av[2] = (char*)command;
107 if (!(proc = procopen(NiL, av, NiL, NiL, flags)))
109 if (!(f = sfnew(f, NiL, -1, (sflags&SF_READ) ? proc->rfd : proc->wfd, sflags)) ||
110 _sfpopen(f, (sflags&SF_READ) ? proc->wfd : -1, proc->pid) < 0)
119 reg int pid, pkeep, ckeep, sflags;
120 int parent[2], child[2];
125 if(!command || !command[0] || !(sflags = _sftype(mode,NIL(int*))))
129 parent[0] = parent[1] = child[0] = child[1] = -1;
132 if((sflags&SF_RDWR) == SF_RDWR && pipe(child) < 0)
137 default : /* in parent process */
139 { pkeep = READ; ckeep = WRITE; }
140 else { pkeep = WRITE; ckeep = READ; }
142 /* make the streams */
143 if(!(f = sfnew(f,NIL(char*),-1,parent[pkeep],sflags)))
145 CLOSE(parent[!pkeep]);
147 if((sflags&SF_RDWR) == SF_RDWR)
148 CLOSE(child[!ckeep]);
150 /* save process info */
151 if(_sfpopen(f,(sflags&SF_RDWR) == SF_RDWR ? child[ckeep] : -1,pid) < 0)
156 #ifdef SIGPIPE /* protect from broken pipe signal */
157 if((sflags&SF_WRITE) &&
158 (sig = signal(SIGPIPE,SIG_IGN)) != SIG_DFL && sig != SIG_IGN)
164 case 0 : /* in child process */
165 (void)_sfpclose(NIL(Sfio_t*));
167 /* determine what to keep */
169 { pkeep = WRITE; ckeep = READ; }
170 else { pkeep = READ; ckeep = WRITE; }
172 /* zap fd that we don't need */
173 CLOSE(parent[!pkeep]);
174 if((sflags&SF_RDWR) == SF_RDWR)
175 CLOSE(child[!ckeep]);
177 /* use sfsetfd to make these descriptors the std-ones */
180 /* must be careful so not to close something useful */
181 if((sflags&SF_RDWR) == SF_RDWR && pkeep == child[ckeep])
182 if((child[ckeep] = dup(pkeep)) < 0)
183 _exit(EXIT_NOTFOUND);
185 if(parent[pkeep] != pkeep)
186 { sf.file = parent[pkeep];
188 if(sfsetfd(&sf,pkeep) != pkeep)
189 _exit(EXIT_NOTFOUND);
192 if((sflags&SF_RDWR) == SF_RDWR && child[ckeep] != ckeep)
193 { sf.file = child[ckeep];
195 if(sfsetfd(&sf,ckeep) != ckeep)
196 _exit(EXIT_NOTFOUND);
199 /* now exec the command */
200 execl("/bin/sh", "sh", "-c", command, NIL(char*));
201 _exit(EXIT_NOTFOUND);
204 case -1 : /* error */
207 { CLOSE(parent[0]); CLOSE(parent[1]); }
209 { CLOSE(child[0]); CLOSE(child[1]); }
212 #endif /*_PACKAGE_ast*/